MVC, CakePHP et Rock’n'Roll !

Metallica calmeJe vous l’accorde, le titre de cet article n’est pas très explicite mais il s’agit d’un simple post mettant en avant l’intérêt des développements utilisant une architecture MVC et de la souplesse que cela apporte, illustré par un exemple. C’est également l’occasion de comprendre en quoi un framework est l’outil idéal vous permettant d’avoir rapidement un code propre, maintenable et faisant exactement ce que vous souhaitez !

Suite à une question posée sur le forum de Developpez.net et paraissant un peu tordue au premier abord, il s’est avéré qu’une solution rapide et assez simple a été trouvée en utilisant chaque couche de l’architecture MVC pour manipuler les données à sa manière. L’utilisation de CakePHP dans ce cas n’est pas vraiment le point clé, mais il faut dire que cela a rendu les choses encore plus intuitives !

Le but de ce problème était de manipuler les données d’une table ayant les champs : TypeProduit, Produit, Annee, Semaine, CA. Il fallait les afficher de manière à avoir : TypeProduit, Produit, CA-AnneeA-SemaineA, CA-AnneeA-SemaineB, CA-AnneeA-SemaineC, CA-AnneeB-SemaineA

Avant de détailler la solution proposée, je tiens juste à dire qu’il y a sans doute encore plus simple et élégant … aussi n’hésitez pas à me faire part des améliorations possibles, c’est ainsi que l’on progresse ! Le code de cet exemple est téléchargeable sur mon compte Github, pour installer la base de données il suffit de lancer la ligne de commande « cake schema run create » … et c’est tout !

La base de données

Dans ce cas précis, c’était un élément qui n’était pas modifiable mais c’est je pense un des point les plus importants d’une application. Si la modélisation de la base de données est suffisamment bien pensée, le code nécessaire ensuite n’en sera que plus simple … Ici il aurait par exemple était intéressant de regrouper les données Années et Semaines dans une table séparée, mais il est difficile de porter un jugement sans plus d’informations !

La plus mauvaise des conceptions sera toujours rattrapable et utilisable par la suite, cela demandera en revanche un travail plus important au niveau du modèle !

Le Modèle

Le but du modèle est de récupérer des données brutes ayant une « signification métier ». Bien que le plus souvent issues de requêtes SQL, ces informations peuvent être récupérées depuis un service web, un système de fichiers ou encore bien d’autres choses. Dans le cas présent, les données que nous souhaitons récupérer sont les CA associés à chaque couple « Année – Semaine » pour chaque Produit.

Une manière simple de récupérer ces informations est de créer une méthode personnalisée dans notre modèle Produit qui se chargera d’interroger la base de données de manière correcte. En voici un code possible (4 lignes !) :

// app/models/produit.php
/**
 * Récupère les Produits de manière à obtenir le CA de chacun par année-semaine
 * @return array Produits groupés
 */
    public function getGrouped() {
        return $this->find('all', array(
            'fields' => array('Produit.name', 'Produit.annee', 'Produit.semaine', 'SUM(Produit.ca) AS ca'),
            'group' => array('Produit.name', 'Produit.annee', 'Produit.semaine')));
    }

L’instruction est assez explicite : nous récupérons les champs « name, annee, semaine et CA » où le CA est la somme de tous les CA ayant en commun un produit, une année et une semaine (remarquez ici que le nom du produit est utilisé comme identifiant unique … nous nous adaptons à la base de données).

Le Contrôleur

Le Contrôleur, souvent appelé la partie « intelligente » de l’application doit récupérer les données aux bons endroits et les assembler de manière à ce que les informations puissent être exploitées de manière simple. Il faut en règle générale essayer de déplacer les manipulations de données « régulières » dans le modèle, dans un but à la fois « DRY » et afin de suivre le précèpte « Fat Models, Skinny Controllers« . Dans le cas présent, nous partirons du principe que le formatage des données n’a rien de « métier » et est exclusivement lié à cette action … le code doit donc se trouver dans le Contrôleur.

Nous récupérons donc des données tabulaires de la forme « name, annee, semaine, ca » et souhaitons avoir un tableau de la forme :

array (
   nameA => array (
      anneeA-semaineA => ca,
      anneeA-semaineB => ca,
   ),
   nameB => ...
);

Il nous faut également avoir la liste des couples année-semaine présents dans nos données. Pour celà, nous utiliserons la librairie Set issue du coeur de CakePHP permettant de remodeler ses tableaux en un claquement de doigt ! Voici le code du contrôleur ProduitsController (désolé pour les noms, je n’avais pas trop d’inspiration :D ) … ~10 lignes de code :

// app/controllers/produits_controller.php
    function dynamique() {
        $data = $this->Produit->getGrouped();
        // Groupe les produits par "name" et crée un tableau indexé par "annee-semaine" contenant la valeur du ca associé
        $produits = Set::combine($data, array('{0}-{1}', '{n}.Produit.annee', '{n}.Produit.semaine'), '{n}.0.ca', '{n}.Produit.name');
        // Crée la liste des semaines présentes dans le résultat, ordonnées par ordre croissant
        $semaines = Set::sort(
            array_keys(
                Set::combine($data, array('{0}-{1}', '{n}.Produit.annee', '{n}.Produit.semaine'))),
            '{n}',
            'asc');
        $this->set(compact('produits', 'semaines'));
    }

La librairie Set est assez peu connue et utilisée mais croyez-moi, dès qu’on s’est mis à l’utiliser on ne peut plus s’en passer ;)

La Vue

Enfin, vient le temps d’afficher les données dans la vue. Il n’y a rien de très complexe ici étant donné que nous avons une variable « $produits » formatée de manière à nous simplifier la vie et la liste des semaines dans la variable « $semaines ». Nous afficherons les données sous forme tabulaire, et quelques foreach plus loin nous voici avec une vue ressemblant à ceci :

<!-- app/views/produits/dynamique.ctp -->
<h2><?php __('Données "dynamiques"')?></h2>
<table>
 <thead>
 <tr>
 <td><?php __('Produit')?></td>
 <?php foreach($semaines as $semaine):?>
 <td><?php echo $semaine?></td>
 <?php endforeach;?>
 </tr>
 </thead>
 
 <tbody>
 <?php foreach($produits as $nom => $data):?>
 <tr>
 <td><?php echo $nom?></td>
 <?php foreach($semaines as $semaine):?>
 <td><?php echo (isset($data[$semaine])) ? $data[$semaine] : '0'?></td>
 <?php endforeach;?>
 </tr>
 <?php endforeach;?>
 </tbody>
</table>

… et voilà, un beau tableau avec des informations pas vraiment directement issues de la base de données !

Conclusion

En quelques lignes de code, voici comment la souplesse de l’architecture MVC nous a permis de récupérer des données et de les manipuler de manière entièrement personnalisée. Cela permet d’avoir une application évolutive qui pourra à tout moment évoluer vers de nouvelles fonctionnalités non prévues au départ.

Nous avons également été bien aidés par la magie et les raccourcis fournis par un framework, pour la manipulation de données, l’intéraction avec la base de données mais aussi l’organisation des fichiers. Il est évident que ce genre d’outils permettent de gagner énormément en productivité, une fois la phase d’apprentissage passée ! Néanmoins un framework est un outil comme un autre, qui doit être avant tout un choix personnel … les aspects « optimisation » et autres devant à mon sens rester secondaires : le but est avant tout de prendre du plaisir à développer !

La raison même de cet article était tout simplement de partager le plaisir que j’ai à développer en utilisant de tels outils et architectures … afin d’aider certains à passer le cap, et à quitter le monde du procédural et des frameworks maisons pour faire confiance aux frameworks open source proposant des méthodes de développement qui sont (nous l’avons vu) très flexibles et permettront d’une manière ou d’une autre d’arriver à ses fins !

Avez-vous franchi le cap ? Quels sont vos retours d’expérience ?

Partagez avec vos amis !
  • del.icio.us
  • Twitter
  • Tumblr
  • Facebook
  • Digg
  • LinkedIn
  • Google Bookmarks
  • email
  • Technorati
  • Wikio FR
  • Netvibes
  • RSS
If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags : CakePHP, framework, Méthode, mvc
  • Flory
    Salut!

    Ca vous dirait pas de faire en sorte que les articles du flux RSS ne soient pas des gros patés ? :)
  • (Désolé pour la traduction via Google. J'ai cessé d'étudier le français à l'école il ya 20 ans ;))

    Merci pour le lien vers mon article! Je trouve cela d'autant plus important que les cadres deviennent plus puissants à maîtriser le concept de la séparation de votre logique métier de votre logique de contrôle.
  • c johann
    Merci pour cet article interessant. Cela m a egalement permit de decouvrir un nouvelle classe de cakephp: set

    bonne continuation
  • Merci a tous pour vos commentaires ... il y a en effet beaucoup a dire sur Set, mais la documentation officielle et les tests permettent de la comprendre bien mieux que n'importe quel tutoriel !

    @Flory : Cela fait un moment que je veux essayer de rendre le flux RSS plus attractif, mais je ne pense pas avoir les bons outils :) Du coup j'ai finalement opte pour une solution de facilite : afficher juste les 500 premiers caracteres ! Pour le reste il faudra revenir ici ;)
blog comments powered by Disqus