préface de membre de l’équipe symfony créateur de … · préface • avant-propos •...

26
Symfony 3 Développez des sites web PHP structurés et performants Bilal AMARNI Préface de Jordi BOGGIANO Membre de l’équipe Symfony Créateur de Composer

Upload: hatu

Post on 28-Sep-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

Préface  •  Avant-propos  •  Architecture du framework • Débuter avec Symfony • Routage et contrôleur • L’injection de dé-pendances • Les templates avec Twig • Les bases de données avec Doctrine2 • Le  répartiteur  d’événements  •  Utiliser les  formulaires  •  La  sécurité  •  Logging et  monitoring  •  Tester  son  application  Symfony  •  Améliorer  les  performances de son application • Annexes 

ISBN

: 978

-2-40

9-011

72-6

39 €

Symfony 3Développez des sites web PHP structurés et performants

Bilal Amarni  est  consultant,  déve-loppeur  PHP  freelance.  Titulaire  de la certification Symfony avec  la men-tion  Expert,  il  maîtrise  complètement  l’architecture  du  framework  ainsi  que son  utilisation.  Dans  cet  ouvrage,  il partage  avec  le  lecteur  l’expérience qu’il a acquise au cours de ses diffé-rentes missions et projets.

Préface de Jordi BOGGIANO Membre de l’équipe Symfony - Créateur de Composer

Ce  livre  sur  Symfony 3  s’adresse  aux  développeurs,  chefs de projets, directeurs techniques, qui souhaitent, grâce à ce  framework,  structurer et organiser  leurs  développements PHP au sein d’un cadre de travail  robuste et professionnel. La  maîtrise de la programmation objet avec PHP est un prérequis indispensable pour tirer le meilleur parti de ces pages. 

Le livre couvre les principaux composants de Symfony 3, consi-déré  aujourd’hui  comme  le  framework PHP de référence.  Il  fournit les connaissances de base qui permettent non seulement de créer un site web, mais également de comprendre et maîtriser son fonctionnement en détail. Un chapitre entier est par exemple consacré à l’architecture du framework.

Les sujets détaillés vont de l’installation de Symfony à la création de tests unitaires et fonctionnels. La gestion des formulaires, des interactions avec une base de données, des templates, de la  journalisation  ou  même  de  la  sécurité  de  l’application  sont autant de thèmes exposés dans le livre.

Le temps de chargement des pages d’un site web étant un élément  crucial, un chapitre délivre les techniques et astuces pour forte-ment améliorer les performances d’une application.

L’auteur a structuré les chapitres pour faciliter l’apprentissage de Symfony  3  et  dévoile  au  fil  des  pages  des conseils, bonnes pratiques et exemples détaillés.

Des éléments  complémentaires  sont  en  téléchargement  sur  le site www.editions-eni.fr.  Pour plus

d’informations :

Symfony 3 Développez des sites web PHP structurés et performants

Bilal AMARNI

Les chapitres du livre

Préface de Jordi BOGGIANO Membre de l’équipe Symfony Créateur de Composer

Sym

fony

3D

ével

oppe

z de

s si

tes

web

PH

P

stru

ctur

és e

t per

form

ants

Téléchargementwww.editions-eni.fr.fr

Sur www.editions-eni.fr :b Code source des exemples

traités dans le livre.

1Table des matières

Préface

Chapitre 1Avant-propos

1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2. Public visé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3. Pourquoi un framework ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.1 header() et echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.2 Éviter la globalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.3 Ne pas réinventer la roue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4. Pourquoi Symfony ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5. Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

6. Objectifs du livre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Chapitre 2Architecture du framework

1. Le patron de conception MVC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271.1 Définitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

1.1.1 La vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271.1.2 Le modèle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281.1.3 Le contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Les éléments à télécharger sont disponibles à l'adresse suivante :http://www.editions-eni.fr

Saisissez la référence ENI de l'ouvrage EI3SYM dans la zone de recherche et validez. Cliquez sur le titre du livre puis sur le bouton

de téléchargement.

lcroise
Tampon

2Développez des sites web PHP structurés et performants

Symfony 3

1.2 En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281.2.1 Le contrôleur frontal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291.2.2 Le routage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291.2.3 Le contrôleur et le modèle . . . . . . . . . . . . . . . . . . . . . . . . . 301.2.4 La vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

2. Architecture de Symfony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.1 Schéma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322.2 Le Service Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.3 Un framework MVC ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.4 Une flexibilité à toute épreuve . . . . . . . . . . . . . . . . . . . . . . . . . . 34

3. Les bundles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.1 Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.2 Un écosystème mature. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4. Les environnements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.2 En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4.2.1 Contexte HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.2.2 Contexte CLI (Command Line Interface). . . . . . . . . . . . . 374.2.3 Exemples de différences selon l’environnement . . . . . . . . 38

Chapitre 3Débuter avec Symfony

1. Créer un projet sous Symfony. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391.1 L’édition « standard » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391.2 Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401.3 Installation via l’installeur Symfony (Linux et Mac OS). . . . . . 401.4 Installation via Composer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

1.4.1 Installer Composer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411.4.2 Créer un projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451.4.3 Les versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

3Table des matières

2. Découvrir Symfony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482.1 Configurer son serveur web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

2.1.1 Serveur web PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482.1.2 Apache et Nginx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

2.2 Structure de l’application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

3. La console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543.1 Emplacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543.2 Les commandes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.2.1 Lister les commandes disponibles . . . . . . . . . . . . . . . . . . . 553.2.2 Exécuter une commande . . . . . . . . . . . . . . . . . . . . . . . . . . 56

3.3 Les options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563.4 Les arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573.5 La commande help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573.6 Exécuter rapidement des commandes . . . . . . . . . . . . . . . . . . . . . 59

3.6.1 Les raccourcis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593.6.2 L’autocomplétion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

4. L’autochargement des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604.1 Le standard PSR-4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614.2 Autres mécanismes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624.3 Le fichier vendor/autoload.php . . . . . . . . . . . . . . . . . . . . . . . . . . 62

5. Installer un bundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635.1 Bundle applicatif spécifique au projet . . . . . . . . . . . . . . . . . . . . . 63

5.1.1 Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635.1.2 Créer un bundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

5.2 Bundle tiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

4Développez des sites web PHP structurés et performants

Symfony 3

Chapitre 4Routage et contrôleur

1. Comprendre le routage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691.1 Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691.2 Le répertoire web et le contrôleur frontal . . . . . . . . . . . . . . . . . . 701.3 Une requête, une action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

2. Format des routes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712.1 Différentes méthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712.2 Les annotations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

3. Configurer le path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733.1 Le path /hello/world. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733.2 Comprendre la notation du contrôleur. . . . . . . . . . . . . . . . . . . . 773.3 Choisir son format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 783.4 Importer ses routes depuis des fichiers externes . . . . . . . . . . . . 793.5 Utiliser des paramètres de substitution . . . . . . . . . . . . . . . . . . . 803.6 Comprendre l’ordre de chargement des routes. . . . . . . . . . . . . . 833.7 Préfixer les routes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 833.8 Ajouter des restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

4. Routage par nom de domaine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 874.1 Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 884.2 Exemple. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 884.3 Explications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5. Le contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 925.1 Récupérer un service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 935.2 Utiliser les « paramètres magiques » . . . . . . . . . . . . . . . . . . . . . . 93

5.2.1 Paramètres de substitution des routes . . . . . . . . . . . . . . . 935.2.2 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

5.3 Générer une URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 955.4 Effectuer une redirection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 965.5 Redirection interne. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

5Table des matières

5.6 Renvoyer des pages d’erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 975.6.1 Le contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985.6.2 La vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

Chapitre 5L’injection de dépendances

1. Une alternative au Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1051.1 Présentation du Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1051.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1061.3 Un patron de conception à utiliser avec précaution. . . . . . . . . 107

2. L’injection de dépendances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1082.1 L’injection de dépendances par le constructeur . . . . . . . . . . . . 1082.2 L’injection de dépendances par setter (mutateur) . . . . . . . . . . 1092.3 L’injection de dépendances par propriété . . . . . . . . . . . . . . . . . 1102.4 Les avantages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1112.5 Une exécution complexifiée. . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

3. Le Service Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123.1 Les services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123.2 Explications au travers d’un service X. . . . . . . . . . . . . . . . . . . . 113

4. Créer un service et configurer ses injections. . . . . . . . . . . . . . . . . . . 1144.1 Créer un service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1144.2 Injection par constructeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1144.3 Injection par méthode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1154.4 Injection par propriété . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1164.5 Injection automatique avec l'autowiring . . . . . . . . . . . . . . . . . 1164.6 Utiliser des paramètres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1184.7 Créer des services « lazy » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

5. Les extensions de bundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1215.1 Le dossier DependencyInjection . . . . . . . . . . . . . . . . . . . . . . . . 1235.2 Les définitions de services depuis un bundle . . . . . . . . . . . . . . 123

6Développez des sites web PHP structurés et performants

Symfony 3

5.3 La configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1245.3.1 Définir une arborescence . . . . . . . . . . . . . . . . . . . . . . . . . 1255.3.2 Les différentes étapes du traitement

de la configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1315.3.3 Récupérer la configuration validée . . . . . . . . . . . . . . . . . 134

5.4 Les « Compiler Passes » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1385.4.1 Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1385.4.2 Les tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1415.4.3 Le Compiler Pass. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

Chapitre 6Les templates avec Twig

1. Un langage accessible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1451.1 Aperçu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1451.2 Pourquoi un nouveau langage ? . . . . . . . . . . . . . . . . . . . . . . . . . 1461.3 Mise en pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1471.4 Remarques sur l’utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1481.5 Notations des templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1491.6 L'annotation @Template. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

2. Layouts (gabarits de pages) et blocks . . . . . . . . . . . . . . . . . . . . . . . . 152

3. Structures de contrôle et tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1603.1 Les conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1603.2 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1613.3 Créer et modifier des variables. . . . . . . . . . . . . . . . . . . . . . . . . . 1633.4 Twig et l’échappement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

3.4.1 Le tag autoescape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1653.4.2 Échappement unitaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 1663.4.3 Modifier la stratégie globale (utilisateurs avancés) . . . . 167

3.5 Inclure des templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

7Table des matières

4. Les filtres et les fonctions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1684.1 Les filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

4.1.1 Utilisation et syntaxe. . . . . . . . . . . . . . . . . . . . . . . . . . . . 1684.1.2 Chaînes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1694.1.3 Échappement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1704.1.4 L’encodage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

4.2 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1724.2.1 Twig et le routage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1734.2.2 Débogage avec la fonction dump. . . . . . . . . . . . . . . . . . . 174

5. Ressources publiques (images, feuilles de style, scripts JS…) . . . . . 1745.1 Comment ces ressources sont-elles synchronisées ? . . . . . . . . 1755.2 Référencer les ressources publiques depuis un template . . . . . 176

Chapitre 7Les bases de données avec Doctrine2

1. Concepts de DBAL, entité et ORM. . . . . . . . . . . . . . . . . . . . . . . . . . 1771.1 DBAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1781.2 Entité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1791.3 ORM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

2. Installer et configurer DoctrineBundle . . . . . . . . . . . . . . . . . . . . . . . 1802.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1802.2 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

3. Les entités et leur mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1823.1 Cas pratique : répertorier des livres . . . . . . . . . . . . . . . . . . . . . . 182

3.1.1 L’entité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1823.1.2 Le mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

3.2 Définir une entité avec @ORM\Entity . . . . . . . . . . . . . . . . . . 1873.3 Gérer les colonnes de la table avec @ORM\Column. . . . . . . . 189

3.3.1 name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1893.3.2 type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1903.3.3 length. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

8Développez des sites web PHP structurés et performants

Symfony 3

3.3.4 unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1913.3.5 nullable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1923.3.6 precision et scale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

3.4 @ORM\Table. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1923.5 Les clés primaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1943.6 Configurer les index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195

3.6.1 @ORM\Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1953.6.2 @ORM\UniqueConstraint . . . . . . . . . . . . . . . . . . . . . . . 196

3.7 Les relations (clés étrangères) . . . . . . . . . . . . . . . . . . . . . . . . . . 1963.7.1 @ORM\OneToOne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1973.7.2 @ORM\ManyToOne . . . . . . . . . . . . . . . . . . . . . . . . . . . 1993.7.3 @ORM\ManyToMany . . . . . . . . . . . . . . . . . . . . . . . . . . 2003.7.4 Relations bidirectionnelles . . . . . . . . . . . . . . . . . . . . . . . . 2023.7.5 Repérer les erreurs de mapping . . . . . . . . . . . . . . . . . . . . 206

4. Utiliser l’EntityManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2084.1 Insertion de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2084.2 Modification de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2104.3 Suppression de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2114.4 Autres actions de l’EntityManager . . . . . . . . . . . . . . . . . . . . . . 212

4.4.1 refresh() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2124.4.2 detach() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213

4.5 Les opérations en cascade. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

5. Les repositories et le DQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2185.1 Les repositories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

5.1.1 Un rôle de centralisateur . . . . . . . . . . . . . . . . . . . . . . . . . 2185.1.2 Les méthodes de base du repository . . . . . . . . . . . . . . . . 2195.1.3 Les méthodes personnalisées du repository . . . . . . . . . . 221

5.2 Le DQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2225.2.1 SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2245.2.2 FROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2245.2.3 JOIN et LEFT JOIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2255.2.4 WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2285.2.5 ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

9Table des matières

5.2.6 Les limites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2345.2.7 Les limites et la pagination . . . . . . . . . . . . . . . . . . . . . . . 235

5.3 Le QueryBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

6. Quelques astuces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2426.1 Utilisation du @ParamConverter . . . . . . . . . . . . . . . . . . . . . . . 2426.2 Les extensions Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

6.2.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2446.2.2 Utilisation d'un slug sur une entité . . . . . . . . . . . . . . . . . 245

Chapitre 8Le répartiteur d’événements

1. Une histoire d’écoute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2491.1 Le dispatching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2501.2 Les listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

2. Les événements du Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2572.1 Les événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2572.2 Exemple : effectuer des tâches asynchrones . . . . . . . . . . . . . . . 258

3. Les événements de la console. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2603.1 Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2603.2 Les événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260

Chapitre 9Utiliser les formulaires

1. Une librairie MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2631.1 Le modèle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2631.2 Le contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2651.3 La vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

2. Fonctionnement du composant. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2672.1 L’objet « Form » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

2.1.1 Soumission . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

10Développez des sites web PHP structurés et performants

Symfony 3

2.1.2 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2682.1.3 Vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268

2.2 Les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2682.3 Les options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2692.4 Les objets « Form » et « FormBuilder » . . . . . . . . . . . . . . . . . . . . 270

2.4.1 Le FormBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2702.4.2 Structure de l’objet Form . . . . . . . . . . . . . . . . . . . . . . . . . 270

2.5 Le mapping avec l’objet de la couche Modèle. . . . . . . . . . . . . . 2722.6 Les différentes représentations des valeurs . . . . . . . . . . . . . . . . 274

2.6.1 Transformation des données . . . . . . . . . . . . . . . . . . . . . . 2742.6.2 Illustration avec le type Date. . . . . . . . . . . . . . . . . . . . . . 275

3. Les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2763.1 L’héritage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2763.2 FormType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

3.2.1 label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2773.2.2 label attr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2773.2.3 data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2773.2.4 required . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2773.2.5 disabled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2783.2.6 mapped . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2783.2.7 property_path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2783.2.8 attr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2793.2.9 trim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2793.2.10error_bubbling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279

3.3 TextType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2803.4 PasswordType. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2803.5 RepeatedType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281

3.5.1 type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2813.5.2 first_options et second_options . . . . . . . . . . . . . . . . . . . 2813.5.3 options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2813.5.4 first_name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2823.5.5 second_name. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2823.5.6 invalid_message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

11Table des matières

3.6 ChoiceType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2823.6.1 choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2823.6.2 expanded et multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2833.6.3 placeholder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2833.6.4 preferred_choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2843.6.5 Types similaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

3.7 EntityType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2843.7.1 class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2853.7.2 choice_label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2853.7.3 query_builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2853.7.4 group_by . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2863.7.5 em . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

3.8 DateType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2863.8.1 widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2863.8.2 format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2873.8.3 model_timezone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2873.8.4 view_timezone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2873.8.5 years. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2883.8.6 months . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2883.8.7 days . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2883.8.8 placeholder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2883.8.9 Types similaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

3.9 FileType. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2893.9.1 multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2893.9.2 Récupérer les fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2893.9.3 Traiter les fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

3.10 CheckboxType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2913.11 SubmitType, ResetType et ButtonType. . . . . . . . . . . . . . . . . . 292

4. Validation des données. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2934.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2934.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

4.2.1 Contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2944.2.2 Configuration des contraintes . . . . . . . . . . . . . . . . . . . . . 294

12Développez des sites web PHP structurés et performants

Symfony 3

4.2.3 Les différents formats de configuration . . . . . . . . . . . . . 3014.2.4 Les options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3044.2.5 Validation d’un objet hors du contexte

d’un formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3074.3 Liste des contraintes et de leurs options . . . . . . . . . . . . . . . . . . 307

4.3.1 NotBlank et NotNull . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3084.3.2 IsNull et Blank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3084.3.3 IsTrue, IsFalse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3094.3.4 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3094.3.5 Email, Url et Ip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3104.3.6 Regex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3114.3.7 Length, Count. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3124.3.8 Range. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3134.3.9 Comparaisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3144.3.10Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3154.3.11File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3154.3.12Image. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3164.3.13Choice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3164.3.14UniqueEntity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3174.3.15Données financières . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3184.3.16Callback. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3194.3.17All . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3204.3.18Valid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320

4.4 Groupes de validation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

5. Créer des formulaires réutilisables. . . . . . . . . . . . . . . . . . . . . . . . . . . 3235.1 La classe AbstractType. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3235.2 Utiliser un formulaire défini dans une classe . . . . . . . . . . . . . . 330

5.2.1 Instanciation manuelle. . . . . . . . . . . . . . . . . . . . . . . . . . . 3305.2.2 Avec l'injection de dépendances . . . . . . . . . . . . . . . . . . . 330

6. Personnaliser le rendu - thèmes de formulaires . . . . . . . . . . . . . . . . 3326.1 Afficher le formulaire manuellement . . . . . . . . . . . . . . . . . . . . 332

6.1.1 form_start() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3336.1.2 form_end() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333

13Table des matières

6.1.3 form_widget(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3346.1.4 form_errors(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3346.1.5 form_label(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3356.1.6 form_row() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3356.1.7 form_rest() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3356.1.8 form_enctype() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3356.1.9 Arborescence des parties de formulaires . . . . . . . . . . . . . 335

6.2 Créer des thèmes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3376.2.1 Formulaire d’exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3376.2.2 Créer et associer un thème de formulaires . . . . . . . . . . . 3386.2.3 Comprendre le nom des blocks . . . . . . . . . . . . . . . . . . . . 342

Chapitre 10La sécurité

1. Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

2. Authentification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3472.1 Pare-feu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3472.2 Pare-feu pour ressources statiques/développement . . . . . . . . . 3482.3 Authentification HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3492.4 Authentification par formulaire de connexion. . . . . . . . . . . . . 3492.5 Déconnexion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353

3. Utilisateurs et rôles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3543.1 Récupérer l’utilisateur courant . . . . . . . . . . . . . . . . . . . . . . . . . 3543.2 L’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3553.3 Les fournisseurs d’utilisateurs . . . . . . . . . . . . . . . . . . . . . . . . . . 356

3.3.1 En mémoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3563.3.2 Fournisseur d’utilisateurs de bases de données. . . . . . . . 3573.3.3 Fournisseur d’utilisateurs personnalisé . . . . . . . . . . . . . . 3593.3.4 Notes additionnelles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363

3.4 Cryptage des mots de passe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3643.4.1 Encodeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3643.4.2 Le salage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365

14Développez des sites web PHP structurés et performants

Symfony 3

3.4.3 Crypter un mot de passe . . . . . . . . . . . . . . . . . . . . . . . . . 3673.5 Les rôles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

4. Autorisations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3714.1 Les rôles, au cœur du processus . . . . . . . . . . . . . . . . . . . . . . . . . 3714.2 Vérifier le rôle de l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . 3724.3 Sécuriser une action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3734.4 Sécuriser une section de l’application . . . . . . . . . . . . . . . . . . . . 3744.5 Sécuriser selon d’autres critères . . . . . . . . . . . . . . . . . . . . . . . . . 3754.6 Pour aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377

Chapitre 11Logging et monitoring

1. Créer des logs avec Monolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3791.1 Journalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3791.2 Monolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380

1.2.1 Le standard PSR-3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3801.2.2 MonologBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

1.3 Le service logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3811.4 Le fichier de logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382

1.4.1 Identifier la cause d'un bogue . . . . . . . . . . . . . . . . . . . . . 3821.4.2 Le problème. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382

1.5 Les gestionnaires (handlers) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3831.5.1 Définir plusieurs gestionnaires . . . . . . . . . . . . . . . . . . . . 3831.5.2 Envoyer des logs par e-mail . . . . . . . . . . . . . . . . . . . . . . . 3841.5.3 Utiliser un tampon (buffer) . . . . . . . . . . . . . . . . . . . . . . . 3851.5.4 Ajouter des informations complémentaires . . . . . . . . . . 385

1.6 Les canaux (channels) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3871.6.1 Ajouter ses propres canaux . . . . . . . . . . . . . . . . . . . . . . . 3871.6.2 Envoyer un enregistrement sur un canal donné. . . . . . . 3881.6.3 Configurer les gestionnaires par canaux . . . . . . . . . . . . . 3881.6.4 Gestion des erreurs 404 . . . . . . . . . . . . . . . . . . . . . . . . . . 389

15Table des matières

2. Le monitoring avec Prometheus et Grafana . . . . . . . . . . . . . . . . . . . 3912.1 Un allié proactif au logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3912.2 Préparation d’une application Symfony pour Prometheus . . . 3922.3 Instrumentaliser les mesures . . . . . . . . . . . . . . . . . . . . . . . . . . . 3972.4 Pour aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398

Chapitre 12Tester son application Symfony

1. Les tests unitaires et fonctionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . 3991.1 Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

1.1.1 L’automobile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4001.1.2 Les tests sous Symfony . . . . . . . . . . . . . . . . . . . . . . . . . . 400

1.2 Installation de PHPUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

2. Tests unitaires. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4012.1 Exécuter les tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4032.2 Exécuter une partie des tests . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

3. Tests fonctionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4043.1 Tester une action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4043.2 L’objet Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4053.3 L’objet Crawler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4083.4 Soumettre un formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4103.5 Pour aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411

Chapitre 13Améliorer les performances de son application

1. La mise en cache de pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4131.1 Autour du protocole HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4131.2 Le proxy inverse (ou « reverse proxy ») . . . . . . . . . . . . . . . . . . . 414

1.2.1 HttpCache. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4161.2.2 Nginx. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4171.2.3 Varnish . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418

16Développez des sites web PHP structurés et performants

Symfony 3

1.3 Les en-têtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4231.4 Les réponses publiques et privées . . . . . . . . . . . . . . . . . . . . . . . 4231.5 L’expiration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424

1.5.1 L’en-tête Expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4241.5.2 Les directives max-age et s-max-age . . . . . . . . . . . . . . . . 4251.5.3 L’annotation @Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 425

1.6 La validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4271.6.1 Par date avec Last-Modified . . . . . . . . . . . . . . . . . . . . . . . 4281.6.2 Par empreinte avec l’en-tête ETag . . . . . . . . . . . . . . . . . . 429

1.7 Les ESI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4301.7.1 Activation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4311.7.2 Générer une balise ESI . . . . . . . . . . . . . . . . . . . . . . . . . . . 431

2. L’autochargement des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4332.1 Générer un classmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4332.2 Englober le chargeur de classe de Composer. . . . . . . . . . . . . . . 433

3. Le cache avec Doctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4343.1 Les différents types de cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 434

3.1.1 Le cache des métadonnées . . . . . . . . . . . . . . . . . . . . . . . . 4343.1.2 Le cache des requêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4343.1.3 Le cache des résultats . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434

3.2 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435

4. Le cache d’annotations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436

5. Les sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437

6. L’extension PHP pour Twig. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4386.1 Installation via PEAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4386.2 Installation depuis les sources . . . . . . . . . . . . . . . . . . . . . . . . . . 438

7. Autres optimisations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4397.1 Choix de sa SAPI PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

7.1.1 Qu'est-ce qu'une SAPI ? . . . . . . . . . . . . . . . . . . . . . . . . . . 4397.1.2 Module du serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4407.1.3 CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4407.1.4 FastCGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441

17Table des matières

7.1.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4417.2 Mise en cache d'OPCodes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441

7.2.1 Les OPCodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4427.2.2 Une étape lourde. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4427.2.3 La mise en cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443

7.3 La compression des réponses . . . . . . . . . . . . . . . . . . . . . . . . . . . 4437.3.1 Compression gzip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4437.3.2 Précompression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444

7.4 Optimisation des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4447.4.1 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4457.4.2 Expiration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4457.4.3 Autres techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445

7.5 Conseils de Google . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446

8. Test des performances d'un site web. . . . . . . . . . . . . . . . . . . . . . . . . 4468.1 Côté serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446

8.1.1 Apache Bench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4468.1.2 Xhprof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447

8.2 Côté client. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447

Annexes

1. Développer son projet Symfony sur une machine virtuelle. . . . . . . 4491.1 Introduction à la virtualisation . . . . . . . . . . . . . . . . . . . . . . . . . 4491.2 Virtualisation et développement web . . . . . . . . . . . . . . . . . . . . 4501.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451

1.3.1 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4521.3.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453

2. Créer une commande pour la console . . . . . . . . . . . . . . . . . . . . . . . . 4542.1 La configuration d’une commande . . . . . . . . . . . . . . . . . . . . . . 4542.2 Les objets input et output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4562.3 Le Service Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4582.4 Commande d’exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459

18Développez des sites web PHP structurés et performants

Symfony 3

3. Envoyer des e-mails grâce à SwiftMailer. . . . . . . . . . . . . . . . . . . . . . 4603.1 Le protocole SMTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4603.2 Le transport. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460

3.2.1 Le transport smtp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4613.2.2 Le transport sendmail. . . . . . . . . . . . . . . . . . . . . . . . . . . . 4643.2.3 Le transport mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4653.2.4 Choisir son transport . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466

3.3 Envoi d'un e-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4673.4 Le spool d'e-mails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4683.5 Pendant le développement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470

4. Gérer ses utilisateurs avec FOSUserBundle . . . . . . . . . . . . . . . . . . . 4714.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4714.2 Aperçu des fonctionnalités. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4724.3 Activation des traductions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4734.4 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474

4.4.1 Création de la classe utilisateur . . . . . . . . . . . . . . . . . . . . 4744.4.2 Configuration de la sécurité. . . . . . . . . . . . . . . . . . . . . . . 4754.4.3 Configuration du bundle . . . . . . . . . . . . . . . . . . . . . . . . . 475

4.5 Importation des routes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4764.6 Inscription des utilisateurs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477

4.6.1 Accéder au formulaire d'inscription . . . . . . . . . . . . . . . . 4774.6.2 Personnaliser le formulaire avec un CAPTCHA . . . . . . . 4774.6.3 Envoi d'un e-mail de confirmation . . . . . . . . . . . . . . . . . 480

4.7 Pour aller plus loin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480

5. Les traductions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4815.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481

5.1.1 La culture (Locale) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4815.1.2 Internationalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4825.1.3 Régionalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482

5.2 Détecter la culture d'un utilisateur . . . . . . . . . . . . . . . . . . . . . . 4825.2.1 Différentes possibilités . . . . . . . . . . . . . . . . . . . . . . . . . . . 4825.2.2 En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483

5.3 Deux principaux cas d'utilisation des traductions . . . . . . . . . . 484

19Table des matières

5.4 Activation des traductions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4845.5 Routes multilingues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4855.6 JMSI18nRoutingBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485

5.6.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4865.6.2 Configuration de la stratégie . . . . . . . . . . . . . . . . . . . . . . 4865.6.3 Traductions des routes . . . . . . . . . . . . . . . . . . . . . . . . . . . 487

5.7 Les fichiers de traductions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4885.7.1 Emplacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4885.7.2 Règle de nommage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488

5.8 Traduction d'un message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4905.8.1 Le service translator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4905.8.2 Les paramètres de substitution (placeholders) . . . . . . . . 4915.8.3 Dans les templates Twig . . . . . . . . . . . . . . . . . . . . . . . . . 491

6. Travailler avec les sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4926.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4926.2 Intégration des sessions dans Symfony . . . . . . . . . . . . . . . . . . 4936.3 Configuration du gestionnaire de sauvegarde . . . . . . . . . . . . . 493

6.3.1 Avec PHP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4936.3.2 Avec Symfony. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494

6.4 Les messages « flash » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495

7. Déployer son application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4967.1 Le déploiement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4967.2 Faut-il déployer par FTP ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4977.3 Les différentes étapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4987.4 Capistrano et Capifony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499

7.4.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4997.4.2 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4997.4.3 Déploiement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501

7.5 Fonctionnalités avancées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503

105

Chapitre 5

L’injection de dépendances

L’injection de dépendances

1. Une alternative au Singleton

Le Singleton est un patron de conception qui a été largement plébiscité durantde nombreuses années, mais il est aujourd’hui sur le déclin.

Il est cependant important de le connaître, en maîtrisant le Singleton, en com-prenant ses faiblesses dans certaines circonstances, vous serez plus à mêmed’appréhender un autre patron de conception indispensable pour développersous Symfony : l’injection de dépendances.

1.1 Présentation du Singleton

Le but du patron de conception Singleton est de limiter le nombre d’instancia-tions possibles d’une classe à… une seule !

Cela semble a priori impossible car une classe peut être instanciée sans limitesgrâce à l’opérateur new. Néanmoins, il existe un subterfuge permettant delimiter ce nombre d’instanciations.

Nous savons que PHP, en rencontrant l’opérateur new, crée une instance dela classe qui suit celui-ci (cela donne lieu à un objet), puis, si elle est définie,invoque la méthode magique __construct de cet objet.

lcroise
Tampon

© E

dit

ions

EN

I -

All r

ights

rese

rved

106Développez des sites web PHP structurés et performants

Symfony 3

Que se passe-t-il si nous changeons la visibilité de cette méthode, en la passanten « privée » par exemple ? PHP déclenchera une erreur fatale, la classe devientdonc non instanciable.

Ce changement de visibilité est la solution pour implémenter ce patron deconception. La méthode __construct(), étant inaccessible, il faudra passer parun système d’instanciation alternatif.

1.2 Exemple

Prenons l’exemple classique d’une classe permettant d’interroger une base dedonnées :

<?php

class MyPDO extends PDO

{

private static $instance;

private function __construct() {}

public static function getInstance()

{

if (!isset(self::$instance)) {

self::$instance = new self(

’mysql:host=localhost’, ’bilal’, ’pass’

);

}

return self::$instance;

}

// ...

}

Ici, la méthode __construct est privée et une méthode statique getInstancepermet d’instancier la classe Singleton, ce qui est impossible en dehors de cetteclasse.

107L’injection de dépendancesChapitre 5

Une fois la classe instanciée, l’objet est mis dans une propriété statique et, à laprochaine invocation de la méthode getInstance, l’objet contenu dans cettepropriété sera directement retourné : la classe n’est instanciable qu’une fois.

Remarque

Les puristes iront même jusqu’à créer une méthode __clone privée, demanière à empêcher le clonage de l’objet retourné par getInstance, car celareviendrait à avoir plusieurs instances de la classe.

1.3 Un patron de conception à utiliser avec précaution

Ce patron de conception peut s’avérer problématique.

Analysons l’exploitation de notre classe Singleton MyPDO précédemmentdéfinie, au sein d’une classe X donnée :

<?php

class X

{

public function foo()

{

$stmt = MyPDO::getInstance()->query(’SELECT...’);

// ...

}

// ...

}

Cette technique est comparable au mot-clé global car elle autorise la récupé-ration de variables (ici un objet) extérieures au contexte courant (une mé-thode).

La conséquence est qu’on ne peut facilement savoir quelles sont les dépen-dances de la classe X. Ici, on aperçoit bien la classe MyPDO, mais imaginezune classe de plusieurs centaines de lignes, pouvant accéder à une classeSingleton à tout moment : il faudrait scruter le corps de chaque méthode pourles repérer !

© E

dit

ions

EN

I -

All r

ights

rese

rved

108Développez des sites web PHP structurés et performants

Symfony 3

Remarque

Comme nous allons le démontrer dans la suite de ce chapitre, il est très impor-tant de connaître et de pouvoir gérer les dépendances de ses classes et com-posants. Cela facilite le refactoring (réécriture de code) et les tests unitairespar exemple. Nous verrons également comment l’injection de dépendancesfavorise la portabilité du code en autorisant une classe à fonctionner avecdifférentes implémentations d’une dépendance.

2. L’injection de dépendances

L’idée qui sous-tend l’injection de dépendances est simple : au lieu de laisserune classe aller chercher elle-même les dépendances dont elle a besoin, ce pro-cessus est externalisé.

La classe X, allégée de cette tâche, pourra se concentrer sur sa fonctionpremière.

Découvrons ci-après les différents types d’injection.

2.1 L’injection de dépendances par le constructeur

Cette injection consiste à passer la dépendance lors de l’instanciation de laclasse :

<?php

class X

{

private $db;

public function __construct(\PDO $db)

{

$this->db = $db;

}

public function foo()

{

$stmt = $this->db->query(’SELECT...’);

109L’injection de dépendancesChapitre 5

// ...

}

// ...

}

Ce type d’injection convient parfaitement aux dépendances obligatoires.

Comme vous pouvez le constater, le TypeHint (typage d’objet) est PDO. Celapermet d’être sûr que l’objet passé en argument lors de l’instanciation est unobjet PDO, ou un objet héritant de PDO.

Remarque

Utiliser un TypeHint s’apparente à passer un « contrat ». Ici, peu importe lecontexte, on sait qu’un objet de la classe X aura toujours à sa disposition unobjet PDO ou héritant de PDO sur lequel il pourra compter. C’est dans sa défi-nition même, la classe X ne peut être instanciée sans objet PDO. Cela n’auraitpas été le cas avec la technique du Singleton, où la classe X dépendrait ducontexte.

2.2 L’injection de dépendances par setter (mutateur)

L’injection via les setters peut être faite à n’importe quel moment de la vie del’objet.

<?php

class X

{

private $db;

public function setDb(\PDO $db)

{

$this->db = $db;

}

public function foo()

{

if ($this->db) {

$stmt = $this->db->query(’SELECT...’);

© E

dit

ions

EN

I -

All r

ights

rese

rved

110Développez des sites web PHP structurés et performants

Symfony 3

//...

}

}

// ...

}

Ce type d’injection est plutôt conseillé pour les dépendances optionnelles, oulorsque l’on souhaite se donner la possibilité de changer l’implémentationd’une dépendance obligatoire.

2.3 L’injection de dépendances par propriété

Ce type d’injection est moins recommandé, car on n’a aucun moyen de véri-fier que le type de la dépendance injectée est correct. Nous vous la présentonstout de même :

<?php

class X

{

public $db;

public function foo()

{

if ($this->db) {

$stmt = $this->db->query(’SELECT...’);

//...

}

}

// ...

}