Pour apprendre Symfony, quoi de mieux que de commencer par un projet ?
En vérité, Symfony 1.0 je l’ai appris avec The Askeet Tutorial qui permet en 24h de faire le tour des fonctions de Symfony. Il ne faut pas rêver, Symfony ne se maîtrise pas en 24h, mais on a de très bonne base pour l’utiliser.
L’idée ici, c’est de construire un CMS (Content management system) en Symfony. Pourquoi ? Parce que c’était mon projet numéro 2 de PHP. Je vais donc vous présenter mon travail.
Les prérequis
Pour commencer il faut avoir de bonnes bases en base de données, en PHP (Version 5 de préférence) et le mieux c’est d’avoir suivi le tutoriel Askeet.
Ensuite au niveau des logiciels :
- Symfony 1.0.19 installé.
- Un WAMP (ou équivalent) : Apache, MySQL, PHP.
- Parce que Notepad++ (ou VI) c’est bien mais… on choisit Eclipse avec les supers plugin SFDT et Clay Database Modeling.
- PhotoShop CS4 pour le design.
Mais aussi savoir ce qu’est un CMS. Pour cela une rapide description s’impose :
Un CMS c’est un logiciel qui permet de gérer du contenu. Autrement dit, cela permet de concevoir et de maintenir un site web en ligne, de pouvoir travailler à plusieurs ou encore de pouvoir structurer du contenu.
Notre CMS disposera d’une arborescence de fichiers ordonnables.
Un fichier sera soit un dossier, soit du contenu.
La base de données
L’idée d’un CMS c’est de pouvoir gérer tout type de contenu, plusieurs utilisateurs, des groupes et des permissions comme on le souhaite.
On peut donc partir sur un modèle de base de données qui est le suivant :
J’ai préfixé toutes mes tables de sf_cms : sf = Symfony, cms = le nom du projet.
La table sf_cms_user
Représentation d’un utilisateur.
Dans ce qui peut ne pas être évident :
- sha1_password / salt : permet d’avoir un mot de passe crypter en sha1 et salé.
- Le stripped-name permet (si besoin) d’avoir une URL conforme pour l’utilisateur.
Exemple : …/cms/william-durand.html
- created_at / updated_at : champs que Symfony utilise et gère tout seul.
Les tables sf_cms_content / sf_cms_content_i18n
L’i18n c’est l’internationalisation (wiki). Symfony gère l’i18n automatiquement dès lors que l’on suffixe une table de _i18n.
Pour les champs de la table :
- object et action : se sont deux champs complémentaire pour la gestion de modules (dans le futur).
Exemple : object = sf_cms_blog (un blog) et son action = list (pour lister les posts du blog par exemple).
- is_public : définit si le contenu est visible.
- is_public_cache : pour la gestion du cache.
- navigation et extra : rapport à un layout CSS en trois parties : Content, Navigation, Extra.
- rank : pour ordonner le contenu dans l’arborescence de fichiers (détaillé plus loin).
- culture : La culture du contenu.
Exemple : culture = fr_FR pour la France.
- file_path : décrit un fichier comme contenu.
- html_body : définit un contenu HTML.
- url : définit un contenu de type lien hypertexte.
- stripped_title : Titre strippé du contenu. (Pour créer une URL d’accès au contenu).
- html_* : pour les méta tags.
Les tables sf_cms_folder / sf_cms_folder_i18n
Un folder est l’équivalent d’un menu. Un folder peut contenir d’autres folder ou des contenus.
On peut ordonner tous les éléments d’un folder.
Les champs sont équivalents à un contenu.
is_empty_cache et first_child_content_id_cache ne serviront pas.
La table sf_cms_group
Un groupe d’utilisateur rassemble plusieurs utilisateurs sous une même fonction.
Un groupe possède des permissions avec aux tables sf_cms_group_credential et sf_cms_group_dynamic_credential. Les utilisateurs héritent de ces permissions.
Les tables sf_cms_credential / sf_cms_dynamic_credential
Les credentials sont les permissions. Il en existe deux sortes.
Les credentials simples (sf_cms_credential) qui sont des permissions définies et fixes, et les dynamic credentials (sf_cms_dynamic_credential) qui sont affectées ou rétirées selon les actions effectuées.
Un exemple de credential : L’accès à la gestion de l’arborescence de fichiers.
Un exemple de dynamic credential : La suppression d’un post uniquement par l’utilisateur qui l’a écrit.
Démarrage du projet
Notre analyse est terminée, la base de données est pensée. Il faut donc commencer le projet. Pour cela, on créé un nouveau projet Symfony sous Eclipse.
Notre projet va se composer de deux applications :
- Un Backend : qui permet de gérer le site, non-accessible aux internautes, seulement pour les utilisateurs qui gèrent le site.
- Un Frontend : qui est la partie visible par les internautes, le site en lui-même.
Il faut donc une arborescence comme celle-ci :
Maintenant avec Clay Azzury il faut designer la base de données. Ce n’est pas très compliqué et j’en passe les détails. A noter que j’utilise HSQLDB 1.8.0 comme SQL Dialect qui est selon mes tests le mieux lors de la convertion du modèle en schéma.
SFDT permet d’un seul clic d’obtenir le schema.yml tant utile à Symfony :
Clic-droit sur le model.clay > Symfony > Convert to Symfony YML-Schema.
On obtient notre schema.yml dans le répertoire config/. Mais l’internationalisation n’est pas gérée. On édite ce fichier, pour les tables *_i18n il faut rajouter :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Pour les tables qui ont l’internationalisation on ajoute dans _attributes :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Notre schema.yml est prêt ! On va maintenant laisser opérer la magie de Symfony. Je suppose que vous savez configurer l’accès à la base de données dans les fichiers database.yml et propel.ini. On va générer nos classes PHP, soit en ligne de commandes soit avec le Symfony-CLI dans les External Tools d’Eclipse.
Symfony fait tout pour nous, la base de données est maintenant en place, nos objets sont créées. Tout est prêt pour passer à la phase de programmation.
Le Backend
C’est l’application non visible par les internautes, c’est celle qui nous prendra le plus de temps. Mais c’est la plus importante et celle qui demande le plus de rigueur.
Voici une idée du résultat à travers quelques captures d’écran :
Page d’authentification.
Gestion de l’arborescence.
1 – Création du premier module : sfCmsUser
C’est ce module qui va gérer les utilisateurs. Comme nous sommes dans l’application Backend, nous allons nous servir des admin-generator que Symfony met à notre disposition.
On crée dans l’application backend le module sfCmsUser pour l’objet SfCmsUser. On nettoie ensuite le cache.
On obtient l’arborescence ci-dessous :
Le principe c’est de modifier le fichier generator.yml situé dans le répertoire config/. Symfony va générer le code PHP pour nous et le gardera en cache. C’est un point à souligner s’il on veut voir les bonnes pratiques de codage Symfony ou encore s’il on veut modifier une partie du template.
On a déjà la base pour gérer les utilisateurs, et ceci sans avoir taper une ligne de code. Je vais commencer par m’occuper de la connexion d’un utilisateur.
On crée deux partial templates/_password.php et templates/_password2.php :
echo input_password_tag('sf_cms_user[password]');
?>
et
GeSHi Error: GeSHi could not find the language (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
On modifie le fichier config/generator.yml :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Ensuite on va ajouter le code suivant dans le fichier lib/model/SfCmsUser.php :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
La méthode setPassword2 ne fait rien, tout est géré par la première méthode. Maintenant, on va s’occuper de la validation en créant le fichier validate/edit.yml :
Voilà pour cette partie, on va désormais attribuer un avatar à un utilisateur, pour cela on suit le snippet adéquat : http://www.symfony-project.com/snippets/snippet/101.
Il ne reste plus que la partie authentification. Pour cela on ajoute le code suivant dans le fichier actions/actions.class.php :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
L’action handleErrorLogin réaffiche le formulaire en cas d’erreur. On crée le fichier templates/loginSuccess.php :
GeSHi Error: GeSHi could not find the language class (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Puis on crée notre validateur validate/login.yml :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Ensuite on crée le validator lib/sfCmsLoginValidator.php :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Dans le fichier lib/myUser.class.php on ajoute le code suivant :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Il ne reste plus qu’à éditer le fichier de configuration config/settings.yml :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Nous avons notre gestion complète des utilisateurs, avec connexion/déconnexion des utilisateurs.
Voilà le résultat :
2 – Le module sfCmsGroup
Ce module permet de gérer les groupes d’utilisateurs. Il est très simple.
On génère le module :
Puis on modifie le fichier generator.yml :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
A noter les champs group_user et group_credential qui on en attribut :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Ce qui permet d’obtenir le résultat suivant :
C’est tout pour ce module. Petit aperçu au passage :
3 – Le module sfCmsCredential
Ce module gère les permissions des utilisateurs. Il est également simple à mettre en place. On génère le module :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Et on modifie le fichier generator.yml comme ceci :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Toujours le petit aperçu :
4 – Le module sfCmsFolder
C’est le module qui m’a pris le plus de temps à réaliser. Il va afficher l’arborescence de notre site. On pourra ajouter du contenu, des dossiers, les classer, les ordonner et les gérer (ajout, modification, suppression).
Le but c’est d’obtenir ça :
On commence par générer le module :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Ensuite, on configure le generator.yml de cette manière :
GeSHi Error: GeSHi could not find the language yml (using path /home/www/willdurand/wordpress/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Le détail de ce module n’est pas terminé.
Le Frontend
C’est l’application visible par les internautes, le site en lui-même. Cette application est donc simple, puisqu’elle ne fait principalement que de l’affichage.
Voilà une capture d’écran du thème choisi et fait par moi-même :
Le détail de cette application n’est pas terminé.
Bilan du projet rendu
Ce qui fonctionne ?
- Dans le backend :
Les modules : utilisateurs, groupes, permissions, tags, blog, marque-pages, et news sont complets.
Au niveau de l’arborescence (module de gestion du contenu) on peut créer, ordonner, changer les emplacements des fichiers (drag’n drop) et bien sûr les modifier ou supprimer. On peut ajouter les types de contenu suivant : page html, lien hypertexte, fichier, ou module.
Les modules possibles sont : blog, marque-pages, et news.
- Dans le frontend :
Les différents types de contenu s’affichent correctement. Le menu également.
Ce qui ne fonctionne pas ?
- Dans le backend :
Les permissions ne sont pas applicables aux contenus. Il n’y a pas de gestion du style CSS, ni de gestion des éléments du layout (navigation, extra).
Les permissions se cumulent. On n’a pas le choix d’enlever une certaine permission sur un utilisateur appartenant à un groupe. On peut seulement lui en ajouter. Pour pallier ce petit problème, il suffit de lui attribuer un groupe plus faible, et lui rajouter des permissions.
Il n’y a pas de recherche, des problèmes lors de l’installation du plugin sfLucene… Nous avons préféré le laisser de côté.
- Dans le frontend :
Pas de gestion du layout (Navigation, extra), pas de recherche, pas d’affichage des tags.
Ce qui n’a pas été simple ?
En premier lieu, comprendre le système de CMS, même en connaissant le principe, on ne s’imagine pas tout ce qu’il peut y avoir derrière, tout ce que cela implique, etc… Ensuite, l’utilisation de Symfony en lui-même n’a pas été spécialement difficile, mais a nécessité des recherches sur Internet pour arriver à nos fins (classique ceci-dit).
La construction du CMS – Backend
La difficulté a été de comprendre le système des permissions. Les fichiers de configuration, les permissions dynamiques, et l’usage qui en est fait dans le CMS. Ensuite, pas de difficultés particulières, un peu de travail pour l’arborescence, et beaucoup de réflexion.
La construction du CMS – Frontend
Notre partie frontend ne fait que de l’affichage. La partie difficile a été la gestion du menu, et des sous-menus. Les fichiers (contenus et menus) sont ordonnés grâce au champ RANK. Afficher un niveau n’est donc pas très compliqué, mais afficher un menu dynamiquement suivant le niveau où l’on se trouve est plus complexe.
Ce qui peut être amélioré ?
La question à laquelle on répond le plus facilement, tout ! Sans exagéré, on peut améliorer tout notre travail.
Au niveau du backend : on peut ajouter tout ce qui ne fonctionne pas (permissions entièrement gérées dans les deux sens, éditions des styles, gestion du layout).
Au niveau du frontend : on peut ajouter la gestion des tags (affichage), la gestion d’une recherche, une meilleure gestion du menu, et une gestion du layout.
Mais aussi, une gestion de la concurrence ou du versioning.




























Un commentaire
Bonjour,
Ton article m’intéresse beaucoup pour me familiariser avec Symfony.
Pourrais-tu corriger les quelques bugs qui cachent le code source que tu cites ?
Ou alors me rediriger vers un autre howto aussi généreux que le tiens en informations utiles ?