symfony-2-dossier-tutorial-debuter-rapidement

Le développement sous Symfony2

Gain de temps, optimisations et sécurité

Les articles sérieux se font rare sur ce blog, et je compte bien évidemment y remédier avec cet article assez long que j’ai rédigé pour un cours de développement. Le jugeant assez comple, j’ai pensé qu’il serait très utile aux utilisateurs voulant s’intéresser au Framework Symfony 2, j’explique donc comment installer, créer un dépot git, générer des bundles ou encore un backoffice complet (à l’aide de CRUD*) depuis une simple base de donnée, mais avant tout je fais une présentation du Framework, en évoquant les nouveautés apparues depuis la versions 1. En fin de partie je ferais un petit bilan des points positifs et négatifs que j’ai connus tout au long de la période où j’ai eu à maîtriser Symfony! Bonne lecture.

Ici, nous allons vous éclairer aux bases du travail collaboratif sous Symfony! Soit :

Installer et créer un projet Symfony en local

(sous Linux avec Apache2 installé, si ce n’est pas le cas, installer LAMP en une seule ligne de commande!)

Créer un Dépôt GIT et connaître les commandes principales

(créer, ajouter, mettre à jour les sources… des sites gratuits de dépôts en ligne : Assembla [qui sera utilisé ici], GitHub, GoogleCode)

Maîtriser le Framework et travailler dessus!

(les contrôleurs, le CRUD, les Bundles open-sources, étude du Framework…)

Symfony est un Framework PHP privilégié par un très grand nombre de développeurs. Axé professionnel, ce Framework est réputé pour sa très grande simplicité à créer une base de site web et ses systèmes de sécurités pré-configurés (encodage SHA 128bits, firewall configurable, redirections sécurisés…). Moyennant une période d’adaptation et de compréhension de ce Framework (via les ressources et la documentation disponibles sur le site www.symfony.com), ce Framework permet de créer des Morceaux de sites (bundles) très rapidement. Dans la suite de cet exposé, nous vous présenterons les principes fondamentaux de Symfony, suivi d’impressions personnelles dans certains domaines ou le développement avec ce Framework a pu être bénéfique ou non.

Préambule : Que contient Symfony?

  • app/ configuration, gestion du cache et des logs, routage, etc.
  • web/ ressources publiques (images, CSS, JavaScript, etc.)
  • bin/ contient les fichiers servant à l’installation des vendors
  • src/ dossier contenant tous les bundles
    • Application (Plusieurs dossiers de ce genre peuvent se générer)
      • Bundle (lieu où se trouve le contenu de vos Bundle)
        • Entity/ modèles
        • Controller/ contrôleurs
        • Repository/ contient vos méthodes personnelles pour vos modèles
        • Resources/ contient les dossiers view/ pour l’affichage, config/ pour les redirections route etc…
        • Tests/ tests unitaires et fonctionnels associés
  • vendor/ contient les librairies propres à Symfony (Doctrine2, Twig, SwiftMailer, outils de sécurisation…)

1. De l’installation à la configuration du Projet sous Symfony

Nous allons aller d’étapes en étapes afin d’expliquer la plupart des caractèristiques et des nouveautés de ce framework, pour avoir personnellement développer en Symfony 1.4. Pour celà nous passons à l’installation de Symfony. Cela repose en plusieurs étapes aussi :

  • Récupération du paquet (une révision Git ou SVN, voire une archive)
    • tar xvzf Symfony_Standard_2.0.4.tgz
    • cette méthode décompresse l’archive dans le répertoire où on se trouve. (il est possible de récupérer le framework depuis un “git clone source officielle pour travailler en commun avec l’équipe de Sensio labs)
  • Installation du Vendor (les bibliothèques utiles)
    • ./bin/vendors install
    • il est important de récupérer les vendors après installation de Symfony pour pouvoir à l’avenir mettre à jour ce dossier simplement sans migrer vers un nouveau dossier. Pour cela il suffira de relancer la même commande.
  • L’optimisation de l’intégration du Framework dans un serveur Apache2 (utilisation de plugins utiles pour la mise en cache, et surtout les droits d’écriture dans les dossiers logs et cache)
    • utiliser ACL pour l’écriture dans les dossiers app/cache et app/logs :
      • sudo apt-get install acl
      • sudo rm -rf app/cache/* app/logs/*
      • sudo setfacl -R -m u:www-data:rwx -m u:estei:rwx app/cache app/logs
      • sudo setfacl -dR -m u:www-data:rwx -m u:estei:rwx app/cache app/logs
  • La création d’un dépôt git ou svn de notre projet est fortement conseillé pour le travail en équipe
    • sudo apt-get install git
    • gedit .gitignore
    • on ajoute les dossiers et fichiers qu’on ne souhaite pas ajouter au dépôt, comme app/logs, app/cache, bin/vendors et app/config/parameters.ini afin que chaque utilisateurs puissent les gérer eux même.
    • Puis on crée notre dépot :
    • git init
    • git add .
    • git commit -m "Initial commit."
    • On crée un dépôt dans n’importe quel site, nous utiliserons Assembla, qui propose un accès sécurisé et gratuit, nous devons d’abord générer une clé rsa :
      • (ssh-keygen -t rsa) >> à faire si vous n’avais pas encore généré de clés
      • (cat ~/.ssh/id_rsa.pub) >> le fichier contient une clé ssh à copier dans votre gestionnaire de dépôt en ligne (exemple Assembla ou github).
    • git remote add mon_projet git@git.assembla.com:mon_projet.git
    • git config --global user.name "pseudo assembla"
    • git config --global user.email maildinsrciption@assembla.com
    • git push mon_projet master
      • Dans le cas d’une récupération du projet, on fait un git clone git@git.assembla.com:mon_projet.git <alias> on remet bien sur les droits ACL dans les dossiers cache et logs
  • La configuration de Symfony (le fichier parameters.ini)
    • cd app/config/
    • cp parameters.ini parameters.ini.dist
      • On édite le fichier parameters.ini pour le faire communiquer à une base de données, on peut très bien lancer sur le navigateur un fichier qui le fera tout seul dans “app_dev.php/_configurator/step/0”
  • Les updates ou la récupération de modifications/fichiers depuis notre dépôt git
    • git pull
    • récupère les mises à jours à la dernière révisions
    • Pour une mise à jour du dépôt il faut procéder ainsi :
      • git add *
      • ajoute les nouveaux fichiers dans la liste de fichiers à mettre dans le dépot (situé dans le dossier .git/)
      • git commit -m "commentaire à mettre”
      • récupère tous les fichiers qui ont été modifiés par rapport à la révision actuelle
      • git push origin master
      • ou : « git push git@git.assembla.com:mon_projet.git master » envoi toutes les modification dans une nouvelle révision du dépôt.

Afin de tester le plus aisément notre projet Symfony2, il convient de paramétrer au minimum le fichier httpd.conf (dans le cas d’un serveur Apache2 sous linux):

  • sudo gedit /etc/apache2/httpd.conf
  • Édite le fichier httpd.conf pour pouvoir accéder facilement au projet via une url de type : « http://localhost:82/app.php/index »
  • NameVirtualHost 127.0.0.1:82

Avant de générer nos premiers Bundle, nous allons présenter des plugins fortements recommandés par Symfony, en lançant e fichier web/config.php il nous recommande d’installer des extensions pour votre serveur apache2 (récupérable dans les paquets synaptic de Linux, ou via un paquet tar):

  • php-apc est un gestionnaire de cache plus robuste et performant que le cache par défaut de PHP
  • php5-intl module d’internationalisation PHP utile à Symfony

Après ces manipulations il s’avérera beaucoup plus simple de travailler sur Symfony par la suite : (génération d’entités, premiers codes dans les contrôleurs et les Repositorys…)

2. Les Bundles, une nouveau système pour Symfony

L’installation complète prend beaucoup de temps, mais généralement plus elle est longue, et plus le développement sera aisé. Ici on peut choisir de tout faire dans un seul Bundle comme de tout séparer. La notion de module est plus complète que dans Symfony1. Ce dernier permettait de créer plusieurs projets composés de modules (exemple un module d’inscription, un module de connexion…) composé de contrôleurs, de modèles et de vues, cependant il n’était pas aisé de connecter les projets les uns aux autres. Symfony2 règle cette lacune et permet notamment de créer des Bundles composés eux-mêmes de modules pouvant être complémentaire à d’autres Bundles.

Un exemple concret vaut mille mots (citation volée!) : On crée un projet de site de microblogging de type www.microblog.com/index/… , on génère un premier bundle qui permettra l’affichage des pages des membres, avec édition/création de posts, navigations dans les pages des autres membres, on a donc un modèle MVC propre (Entités propres générés par une base de données, des contrôleurs et des vues le tout accessible depuis app/config/routing.yml) = un modèle de page identique, le même css, le même code javascript etc… Maintenant on veut une nouvelle partie plus personnelle comme la partie profil de type www.microblog.com/profil/… en gros on peut éditer ses infos, retrouver tous ces posts pour gérer les commentaires etc, consulter sa liste d’amis, on recrée un bundle et on génère de nouveau les entités utiles (celle de votre base de données, ça peut être la même chose que celui du Bundle précédent), avec un nouveau style de page (css, js, disposition légèrement différente…) mais tout de même la possibilité de revenir vers www.microblog.com/index/… vu que ça doit être le plus transparent possible. Je ne suis pas assez clair? Un autre exemple : Un bundle pour le site public, un autre bundle pour le backoffice … ah oui là vous comprenez un peu l’intérêt! On peut faire un bundle pour une partie d’un site, ou pour en faire un simple outil, que l’on peut appeler depuis n’importe quel Bundle comme une Classe d’ »objet » hérité voici un exemple avec le Bundle FOSUserBundle qui gère la connexion des utilisateurs sur un site en Symfony:

  • <?php
    // src/Acme/UserBundle/Entity/User.php
    
    namespace AcmeUserBundleEntity;
    
    use FOSUserBundleEntityUser as BaseUser;
    use DoctrineORMMapping as ORM;
    
    /**
     * @ORMEntity
     * @ORMTable(name="fos_user")
     */class User extends BaseUser
    {
        /**
         * @ORMId
         * @ORMColumn(type="integer")
         * @ORMGeneratedValue(strategy="AUTO")
         */    protected $id;
        public function __construct()
        {
            parent::__construct();
            // your own logic
        }
    }
  • La création du premier Bundle (Une première vision de son application Web)
    • php app/console generate:bundle --namespace=Acme/HelloBundle --format=yml
    • il faut créer une règle de route pour pointer vers ce bundle dans app/config/routing.yml :
      • AcmeHelloBundle: 
         resource: "@AcmeHelloBundle/Resources/config/routing.yml" 
         prefix: /hello
    • la suite est expliqué sur http://symfony.com/doc/current/book/page_creation.html

Les Bundles sont des “briques” pouvant implémenter un meme projet, des centaines de Bundles ouverts sont disponibles à cette adresse : http://symfony2bundles.org/

Pour activer un nouveau Bundle (non généré par l’invite de commande vue précédemment), il faut commencer par :

  • éditer app/autoload.php pour charger ce bundle
  • $loader->registerNamespaces(array( 
     // ... 
     'FOS' => __DIR__.'/../vendor/bundles', 
     ));
  • éditer app/AppKernel.php pour activer ce Bundle parmi les Bundle existant
  • public function registerBundles() 
     { 
     $bundles = array( 
     // ... 
     new FOSUserBundleFOSUserBundle(), 
     ); 
     }

Symfony2 n’est pas encore aboutit, il n’existe pas de commandes automatiques permettant d’ajouter et d’activer un Bundle récupéré. Généralement ce genre de lacune est corrigé au fil des versions

3. Les modèles, de la générations d’entités aux CRUD

Symfony permet à la fois de créer ces entités manuellement pour créer une base de données, comme de les générer depuis une base de données existante.

  • php app/console doctrine:generate:entity --entity="AcmeHelloBundle:Product" --fields="name:string(255) price:float description:text"
    • Cette simple commande génère un fichier Product.php dans le dossier entities du Bundle, contenant les variables “private $name…” et méthodes getName(), setName()..

Dans le cas d’un projet reposant sur une base de données existante, il est plus judicieux de générer automatiquement ces entités d’après la base de données ajouté dans le fichier parameters.ini :

  • php app/console doctrine:mapping:import AcmeBlogBundle annotation (ou yml/xml)
  • php app/console doctrine:generate:entities AcmeBlogBundle

Puisque vous n’aurez que les méthodes de base, vos entités peuvent être agrémenté de vos méthodes personnelles, il est conseiller de laisser comme tel vos entités (si vous les mettez à or en changeant des éléments dans votre BDD, vous risquez de perdre vos autres méthodes) et de créer un dossier Repository/ dans votre Bundle :

  • Repository/ProductRepository.php
  • namespace PolygonsFrontendBundleRepository;
  • Entity/Product.php Il vous faudra rajouter ce lien dans votre Entité :
  • namespace PolygonsFrontendBundleEntity; 
    use DoctrineORMMapping as ORM; 
    /** 
    * PolygonsFrontendBundleEntityProduct 
    * @ORMTable(name="product") @ORMEntity(repositoryClass="PolygonsFrontendBundleRepositoryProductRepository") 
    */ 
    class Product{ 
    //...

Vous pourrez appeler ces méthodes dans vos Contrôleurs, et afficher les résultats dans vos vues. Une méthode Simple d’affichage de vos tables entières, avec listing des tables, insertions et modification est meme possibles avec la méthode CRUD (très pratique pour un back-office) :

    • ./app/console doctrine:generate:crud --no-interaction --entity="AcmeLibraryBundle:Product" --route-prefix="/prod" --with-write --format="annotation"
    • Cette méthode crée le Controlleur, l’entité et le vue complète.
    • Il ne vous reste plus qu’a créer vos routes dans config/routing.yml de votre Bundle pour afficher toutes les pages générés.

Il s’avère que la méthode CRUD n’est pas sure à 100%, d’après certains tests, il demeure quelques fois des erreurs dans les clés étrangères.

4. Les différences avec les premières versions

Symfony2 à beaucoup évoluer depuis la version 1, tellement quelle n’est plus rétro-compatible, au point qu’on en fini par repérer que quelques ressemblances! EN effet, ce qui ne différe pas énormément de Symfony1 est :

  • Le routing au format yml, récupère le mémé type de configuration
  • Le système MVC reste le même, l’arborescence change
  • Doctrine2
  • certaines methodes restent sensiblement les memes :
    • $session = $this->getRequest()->getSession(); // la plupart des getRequests

Pour ce qui est des changements majeurs :

  • L’apparition des Bundles
  • Les plugins ont évolués, ils sont devenus à la fois des Bundles et aussi peuvent se situer dans le dossier vendor (exemple : swiftmailer)
  • les routing, les entités ou même les vues peuvent être interprétés jusqu’à 3 format : PHP, XML et YML
  • Twig, un nouveau moteur de template
  • Une nouvelle interface de deboggage plus précise et intuitive
  • Une arborescence plus simple, encore volumineuse et déroutante mais beaucoup moins que symfony1.
  • De nouvelles commandes pratiques et plus rapide pour générer des Bundle, des entités etc…
  • D’après les concepteurs de Symfony, un Framework plus rapide et sécurisé.

5. Conclusion : Ce qu’apporte vraiment Symfony2

Symfony2 est une évolution très attendue qui comble un problème qui existait dans sa version 1 : Les Dependency Injection. cette extension permet d’utiliser des services qui sont utilisés dans des Bundles pour être pleinement intégrés à l’application. Tous les Bundles passent par ce système “centralisé” et sont facilement récupérables depuis tous les Contrôleurs. De nombreuses autres fonctionnalités font de Symfony, non pas un Framework mais un outil complet constitués de solutions universelles. Il permet concrètement de créer une application très rapidement, de le faire évoluer facilement (ajout d’élément dans la base de données, nouvelle interface, nouveaux modules) sans toucher aux autres éléments, cela permet d’éviter d’énorme perte de temps en correction de bugs et adaptation de code, c’est donc positif pour le développeur comme le client ou l’utilisateur.

A celà s’ajoute un chapitre important non cité dans ce rapport, celui de la sécurité (config/firewall.yml), permettant de sécuriser à la manière d’un .htaccess des méthodes POST/GET dans des pages de connexion par exemple. voir http://symfony.com/doc/current/book/security.html

Article relatifs