42 bonnes pratiques pour Symfony2

Tugdual Saunier (@tucksaun)

Attention

Ce qui suit n'est trié ni par importance, ni par criticité.

Bien entendu toute bonne pratique est discutable.

Il y a toujours des exceptions.

Soyez donc pragmatiques!

Et remettez dans le contexte.

Pour commencer

Documentation

La documentation est abondante.

Lisez la.

Documentation

Vous l'avez déja lue?

Relisez la réguliérement

Documentation

Quand vous cherchez de la doc ou de l'aide.

Utilisez Symfony2 (majuscule, pas d'espace).

Il y a tellement de ressources disponibles pour symfony (1.x) que vous perdriez du temps à trier.

Bootstrapping

À moins d'être à l'aise et de maîtriser parfaitement Symfony2,

Utilisez la Standard Edition.

Bootstrapping

Utilisez la Standard Edition.

Mais nettoyez!

  • Supprimez le AcmeDemoBundle
  • Supprimez les dépendances dont vous n'avez pas besoin
  • Changez le favicon
  • etc

Profiler

La Web Debug Toolbar vous donne de nombreuses informations utiles.

Ayez toujours un oeil dessus.

Profiler

Interceptez les redirections (en dev).

Cela vous facilitera le debug et vous permettra de voir plus facilement les informations collectées par le profiler.

Organisation

SCM ignore

  • app/cache/*
  • app/logs/*
  • app/bootstrap.php.cache
  • web/bundles
  • vendor
  • app/config/parameters.yml

 

Mais pour ce dernier, inclure un fichier app/config/parameters.yml.dist

Vos mots de passe sont confidentiels!

  • Ne mettez pas d'identifiants en dur dans la configuration (utilisez les parameters)
  • Ne versionnez pas votre parameters.[ini|yml]
  • Utilisez les variables d'environnements

Vos mots de passe sont confidentiels!

# app/config/config.yml
doctrine:
    dbal:
        username: %database_username%
        password: %database_password%

Vos mots de passe sont confidentiels!

# app/config/parameters.yml
parameters:
    database_username:  symfony
    database_password:  s3cr3t

Vos mots de passe sont confidentiels!

<VirtualHost *:80>
    Servername www.domain.tld
    # ...
    SetEnv SYMFONY__DATABASE_USERNAME "symfony"
    SetEnv SYMFONY__DATABASE_PASSWORD "s3cr3t"
</VirtualHost>

Vos mots de passe sont confidentiels!

Ce n'est pas limité aux mots de passe, valable pour toute information 'confidentielle'.

Coding Style

Respectez tout le temps le même coding style.

De préférence suivez celui de Symfony2.

Coding Style

Un outil est disponible pour vous aider à respecter le coding style Symfony2:

PHP Coding Standards Fixer

http://cs.sensiolabs.org/

Applications? Application!

Par défaut, une seule application existe dans un projet Symfony2.

Il est extrêmement rare d'en avoir besoin de plusieurs, réfléchissez-y bien.

Applications

Si vous voulez vraiment en utiliser plusieurs,

votre arborescence doit être uniforme et respecter un maximum celle de la Standard Edition (dossier app).

Bundles

Votre projet est composé de Bundles.

Bundles

Un Bundle = Une Fonctionnalité

UserBundle    => Gestion Utilisateur
ForumBundle   => Forum
ProductBundle => Gestion de produits
StoreBundle   => E-Commerce

Si vos bundles ont pour vocation à être réutilisés,

et si vos bundles sont découplés.

Bundles & Components/Librairies

Idéalement, vos bundles ne doivent être que le lien entre Symfony2 et votre logique métier.

Cette logique métier doit être indépendante.

Inspirez vous du découplage entre Bundles et Components de Symfony2.

Bundles & Components/Librairies

Symfony\Bundle\FrameworkBundle\DependencyInjection

Symfony\Component\DependencyInjection

 

Symfony\Bundle\FrameworkBundle\Validator

Symfony\Component\Validator

 

Symfony\Bundle\FrameworkBundle\HttpKernel

Symfony\Component\HttpKernel

 

Symfony\Bundle\TwigBundle

\Twig

Routing

Aucune route ne doit être déclarée dans app/config/routing.yml.

Ce fichier doit uniquement contenir des imports, les déclarations des routes doivent se trouver dans le même bundle que le controlleur associé à cette route.

Templating

Suivez les conseils de Grégoire Pineau ;)

I18N

Internationalisez dès le début

L'internationalisation après coup est bien plus longue et complexe.

Controlleurs

Forms

Après le traitement avec succès en POST, vous devez toujours rediriger l'utilisateur :

  • sécurité
  • ergonomie
  • évite la duplication

ORM

Les queries doivent être créées dans des classes dédiées (Repository, Peer), pas dans les controlleurs.

Incontournable

Aucun code métier dans les controlleurs.

Ils doivent récupérer les services (ou instancier les objets métier) et les appeler puis passer le résultat à la vue.

C'est tout!

Longueur

Max 20 lignes par action

Au dessus, cela signifie souvent qu'ils contiennent de la logique métier.

Pas plus de 10 actions par controlleurs

Au dessus, ça devient inmaintenable.

Longueur

Les annotations peuvent vous permettre de garder vos controlleurs légers et sans fioritures.

 

Elles vous permettent également de centraliser l'information et de rassembler une déclaration de route avec l'action associée.

Modèle

"Utils"

Ne créez pas de classes "utilitaires" remplies de méthodes statiques.

Forms

Ecrivez vos formulaires dans des form types.

  • Réutilisablité
  • N'alourdit pas les controlleurs
  • Organisation plus "propre"

Forms

Déclarez ces types en services.

Forms

Si vos form types ont des dépendances, injectez les par le constructeur, pas par les options.

Sessions

La logique de persistance en session doit se trouver dans un service avec la session injectée.

Pas dans les controlleurs.

Sessions

Minimisez la quantité de données en session.

Logging

La configuration par défaut de monolog n'écrira les logs de débug qu'en cas d'erreur.

N'hésitez donc pas à logger.

ORM

Utilisez vos entités pour le stockage d'informations.

Utilisez des classes métiers dédiées pour les manipuler.

"Treat your entities like princesses".

Facilite les TU, le refactoring et le découpage bundles/components.

DIC

DIC

Le DIC est sans doute l'outil le plus puissant de Symfony2.

C'est lui qui apporte toute sa flexibilité à Symfony2.

Lisez, apprenez, testez!

DIC

Utilisez la configuration XML dans vos bundles.

DIC

N'injectez pas le container.

Injectez uniquement les dépendances nécessaires.

DIC

Ne mettez pas de chemin en dur.

Vous pouvez utiliser %kernel.root_dir% ou déterminer les chemins au moment de la compilation du DIC.

Vue

Utilisez Twig

Il vous contraindra à respecter le MVC

Utilisez Twig

  • Intuitif
  • Performant
  • Puissant
  • Sécurisé (Autoescaping)

Assets

Utilisez Assetic

Extensibilité / Maintenabilité

Bundles

Vous ne devez pas avoir d'import de configuration des bundles dans app/config/config.yml.

C'est l'extension DI du bundle qui doit s'en charger.

Bundles

Utilisez la configuration sémantique

# app/config/config.yml
my_bundle:
    foo: bar
    my_feat_is_enabled: true
    feat_config:
        lorem: ipsum

Bundles

Validez cette configuration vous permet:

  • de modulariser (charger si nécessaire) vos services.
  • de vous assurer que la configuration est correcte au moment du warmup...
  • et d'afficher des messages clairs au développeur en cas d'erreur.

Commandes

Ecrivez des commandes pour vos batches et tâches répétitives.

Tests

Testez unitairement et fonctionnellement!

PROD

Front controller

Ne déployez pas web/app_dev.php

Pour être plus précis, le seul front controller à déployer est web/app.php

Forms

Surtout ne désactivez pas le CSRF.

Forms

Changez la clef secret du parameters.yml!

Forms

Rappelez vous, "Vos mots de passe sont confidentiels!".

Le secret l'est également!

(D'où son nom)

Forms

Encore mieux, utilisez en plus l'option intention dans vos formulaires.

Cela rendra le token unique pour chaque type de formulaire.

Doctrine

Activez les caches Doctrine (metadata et query).

Aucune incidence sur le fonctionnement, juste sur les perfs.

Personnalisez vos pages d'erreurs

  • C'est plus classe
  • Évite de reconnaître la page d'erreur par défaut

Logs

La configuration de monolog est très bien pour la prod.

N'activez pas le log de toutes les requêtes!

Cache

Cacher les pages est simple avec Symfony2.

Ne générez pas deux fois le même contenu, mettez en cache.

PHP

Utilisez PHP 5.4.

Vous gagnerez en performance et en consommation mémoire.

PHP

Installez et activez APC.

Vous gagnerez en performance.

(Ne sera normalement plus nécessaire avec PHP 5.5 ;) )

Pour finir

N'oubliez pas que Symfony2 est un Framework PHP Objet

Ne vous demandez donc pas

"Comment faire ceci en Symfony2",

 

mais demandez vous

"Comment faire ceci en PHP Objet".

Respectez les bonnes pratiques PHP.

Respectez les bonnes pratiques de la POO.

  • Pas de références
  • Pas de globals
  • Pas de short tags
  • Type Hinting
  • UTF-8
  • PSR-x
  • ...

ainsi que celles du CSS, HTML, JavaScript, Twig, etc ...

en bref, respectez également les bonnes pratiques de tous les autres outils que vous utilisez.

mais également celles du web, de la gestion de projet, du développement en général.

Questions ?

Merci à tous