Manuel sur les fondamentaux de Symfony2

Contents at a Glance
Les fondamentaux de Symfony2 et HTTP..............4
Symfony2 versus PHP pur .........14
Installer et Configurer Symfony ..............27
La création de pages avec Symfony2 .......34
Le Contrôleur ..............48
Routage..........60
Créer et utiliser les templates.....73
Doctrine et les bases de données.............91
Propel et les bases de données ..............115
Les Tests.......123
Validation.....137
Formulaires ...............146
La sécurité ....172
Le Cache HTTP .........195
Traductions...............211
Service Container.......224
Performance ..............235
Composants Internes ..............238
L'API stable de Symfony2........247 Contents at a Glance | iii
Chapter 1
Les fondamentaux de Symfony2 et HTTP
Félicitations! Grâce à l'apprentissage de Symfony2, vous êtes sur la bonne voie pour devenir un développeur web plus productif et populaire (en fait la popularité ne dépend que de vous). Symfony2 est construit de manière à revenir à l'essentiel : implémenter des outils qui vous aident à développer plus rapidement et à construire des applications plus robustes, sans pour autant vous gêner dans votre progression. Symfony repose sur les meilleures idées provenant de diverses technologies : les outils et concepts que vous êtes sur le point d'apprendre représentent les efforts de milliers de personnes depuis de nombreuses années. En d'autres termes, vous n'apprenez pas juste "Symfony", vous apprenez les fondamentaux du web, les bonnes pratiques de développement, et comment utiliser de nombreuses nouvelles bibliothèques PHP, internes ou indépendantes de Symfony2. Alors, soyez prêt !
Fidèle à la philosophie de Symfony2, ce chapitre débute par une explication du concept fondamental du développement web : HTTP. Quelles que soient vos connaissances ou votre langage de programmation préféré, ce chapitre doit être lu par tout un chacun.
HTTP est simple
HTTP (HyperText Transfer Protocol pour les geeks) est un langage texte qui permet à deux machines de communiquer ensemble. C'est tout ! Par exemple, lorsque vous regardez la dernière BD de xkcd1, la conversation suivante (approximative) se déroule:
Et alors que l'actuel langage utilisé est un peu plus formel, cela reste toujours très simple. HTTP est le terme utilisé pour décrire ce simple langage texte. Et peu importe comment vous développez sur le web, le but de votre serveur est toujours de comprendre de simples requêtes composées de texte, et de retourner de simples réponses composées elles aussi de texte.
Symfony2 est construit sur les bases de cette réalité. Que vous le réalisiez ou non, HTTP est quelque chose que vous utilisez tous les jours. Avec Symfony2, vous allez apprendre comment le maîtriser.
Étape 1: Le Client envoie une Requête
Chaque conversation sur le web débute avec une requête. La requête est un message textuel créé par un client (par exemple: un navigateur, une application smartphone, etc...) dans un format spécial connu sous le nom d'HTTP. Le client envoie cette requête à un serveur, et puis attend la réponse.
Jetez un oeil à la première partie de l'interaction (la requête) entre un navigateur et le serveur web xkcd:
Dans le langage HTTP, cette requête HTTP ressemblerait à quelque chose comme ça:
Listing 1-1 1 GET / HTTP/1.1 2 Host:
3 Accept: text/html
4 User-Agent: Mozilla/5.0 (Macintosh)
Ce simple message communique tout ce qui est nécessaire concernant la ressource que le client a demandée. La première ligne d'une requête HTTP est la plus importante et contient deux choses: l'URI et la méthode HTTP.
L'URI (par exemple: /, /contact, etc...) est l'adresse unique ou la localisation qui identifie la ressource que le client veut. La méthode HTTP (par exemple: GET) définit ce que vous voulez faire avec la ressource.
Les méthodes HTTP sont les verbes de la requête et définissent les divers moyens par lesquels vous pouvez agir sur la ressource:
GET Récupère la ressource depuis le serveur
POST Crée une ressource sur le serveur
PUT Met à jour la ressource sur le serveur DELETE Supprime la ressource sur le serveur
Avec ceci en mémoire, vous pouvez imaginer ce à quoi ressemblerait une requête HTTP pour supprimer une entrée spécifique d'un blog, par exemple:
Listing 1-2 1 DELETE /blog/15 HTTP/1.1
Il y a en fait neuf méthodes HTTP définies par la spécification HTTP, mais beaucoup d'entre elles ne sont pas largement utilisées ou supportées. En réalité, beaucoup de navigateurs modernes ne supportent pas les méthodes PUT et DELETE.
En plus de la première ligne, une requête HTTP contient invariablement d'autres lignes d'informations appelées entêtes de requête. Les entêtes peuvent fournir un large éventail d'informations telles que l'entête Host, le format de réponse que le client accepte (Accept) et l'application que le client utilise pour effectuer la requête (User-Agent). Beaucoup d'autres entêtes existent et peuvent être trouvés sur la page Wikipedia List of HTTP header fields2 (anglais).
Étape 2: Le Serveur retourne une réponse
Une fois que le serveur a reçu la requête, il connaît exactement quelle ressource le client a besoin (via l'URI) et ce que le client souhaite faire avec cette ressource (via la méthode). Par exemple, dans le cas d'une requête GET, le serveur prépare la ressource et la retourne dans une réponse HTTP. Considérez la réponse du serveur web xkcd :
Traduit en HTTP, la réponse envoyée au navigateur va ressembler à quelque chose comme ça :
Listing 1-3 1 HTTP/1.1 200 OK
2 Date: Sat, 02 Apr 2011 21:05:05 GMT
3 Server: lighttpd/1.4.19
4 Content-Type: text/html
La réponse HTTP contient la ressource demandée (le contenu HTML dans ce cas), ainsi que d'autres informations à propos de la réponse. La première ligne est spécialement importante et contient le code de statut de la réponse HTTP (200 dans ce cas). Le code de statut communique le résultat global de la requête retournée au client. A-t-elle réussi ? Y'a-t-il eu une erreur ? Différents codes de statut existent qui indiquent le succès, une erreur, ou que le client a besoin de faire quelque chose (par exemple: rediriger sur une autre page). Une liste complète peut être trouvée sur la page Wikipedia Liste des codes HTTP.
Comme la requête, une réponse HTTP contient de l'information additionnelle sous forme d'entêtes HTTP. Par exemple, Content-Type est un entête de réponse HTTP très important. Le corps d'une même ressource peut être retournée dans de multiples formats incluant HTML, XML ou JSON et l'entête Content-Type utilise les Internet Media Types, comme text/html, pour dire au client quel format doit être retourné. Une liste des médias types les plus communs peut être trouvée sur la page Wikipedia Liste de media type usuels.
De nombreuses autres entêtes existent, dont quelques-uns sont très puissants. Par exemple, certains entêtes peuvent être utilisés pour créer un puissant système de cache.
Requêtes, Réponses et Développement Web
Cette conversation requête-réponse est le procédé fondamental qui régit toute communication sur le web. Et tout aussi important et puissant que ce procédé soit, il est inéluctablement simple.
Le plus important est que : quel que soit le langage que vous utilisez, le type d'application que vous construisez (web, mobile, API JSON), ou la philosophie de développement que vous suivez, l'objectif final d'une application est toujours de comprendre chaque requête et de créer et retourner la réponse appropriée.
Symfony est conçu pour correspondre à cette réalité.
Pour en savoir plus à propos de la spécification HTTP, lisez la RFC originale HTTP 1.1 RFCou le HTTP Bis, qui est un effort actif pour clarifier la spécification originale. Un super outil pour inspecter/vérifier les entêtes de la requête et de la réponse durant votre navigation est l'extension pour Firefox Live HTTP Headers.
Requêtes et réponses en PHP
Alors comment interagissez-vous avec la «requête» et créez-vous la «réponse» quand vous utilisez PHP ? En réalité, PHP vous abstrait une partie du processus global:
Listing 1-4 1 $uri = $_SERVER['REQUEST_URI'];
2 $foo = $_GET['foo'];
4 header('Content-type: text/html');
5 echo 'L\'URI demandée est: '.$uri;
6 echo 'La valeur du paramètre "foo" est: '.$foo;
Aussi étrange que cela puisse paraître, cette petite application utilise les informations de la requête HTTP afin de créer une réponse. Plutôt que d'analyser le message texte de la requête HTTP directement, PHP prépare des variables superglobales telles que $_SERVER et $_GET qui contiennent toute les informations de la requête. De même, au lieu de retourner la réponse texte HTTP formatée, vous pouvez utiliser la fonction header() pour créer des entêtes de réponse et simplement délivrer le contenu actuel qui sera la partie contenu du message de la réponse. PHP va ainsi créer une véritable réponse HTTP et la retourner au client :
Listing 1-5 1 HTTP/1.1 200 OK
2 Date: Sat, 03 Apr 2011 02:14:33 GMT
3 Server: Apache/2.2.17 (Unix)
4 Content-Type: text/html
5
6 L'URI demandée est: /testing?foo=symfony
7 La valeur du paramètre "foo" est: symfony
Requêtes et Réponses dans Symfony
Symfony fournit une alternative à l'approche brute de PHP via deux classes qui vous permettent d'interagir avec la requête et la réponse HTTP de manière plus facile. La classe Request8 est une simple représentation orientée objet du message de la requête HTTP. Avec elle, vous avez toute l'information de la requête à votre portée:
Listing 1-6 1 use Symfony\Component\HttpFoundation\Request;
2
3 $request = Request::createFromGlobals();
4
5 // l'URI demandée (par exemple: /about) sans aucun paramètre
6 $request->getPathInfo();
7
8 // obtenir respectivement des variables GET et POST
9 $request->query->get('foo');
10 $request->request->get('bar', 'valeur par défaut si bar est inexistant'); 11
12 // obtenir les variables SERVER
13 $request->server->get('HTTP_HOST');
14
15 // obtenir une instance de UploadedFile identifiée par foo
16 $request->files->get('foo');
17
18 // obtenir la valeur d'un COOKIE value
19 $request->cookies->get('PHPSESSID');
20
21 // obtenir un entête de requête HTTP request header, normalisé en minuscules
22 $request->headers->get('host');
23 $request->headers->get('content_type'); 24
8.
25 $request->getMethod(); // GET, POST, PUT, DELETE, HEAD
26 $request->getLanguages(); // un tableau des langues que le client accepte
En bonus, la classe Request effectue beaucoup de travail en arrière-plan dont vous n'aurez jamais à vous soucier. Par exemple, la méthode isSecure() vérifie les trois valeurs PHP qui peuvent indiquer si oui ou non l'utilisateur est connecté via une connexion sécurisée (c-a-d https).
Attributs de ParameterBags et Request
Comme vu ci-dessus, les variables $_GET et $_POST sont accessibles respectivement via les propriétés publiques query et request. Chacun de ces objets est un objetParameterBagqui a des méthodes comme get(), has()11, all()et bien d'autres. En fait, chaque propriété publique utilisée dans l'exemple précédent est une instance de ParameterBag.
La classe Request a aussi une propriété publique attributes qui contient des données spéciales liées au fonctionnement interne de l'application. Pour le framework Symfony2, la propriété attributes contient les valeurs retournées par la route identifiée, comme _controller, id (si vous utilisez le joker {id}), et même le nom de la route (_route). La propriété attributes existe pour vous permettre d'y stocker des informations spécifiques liées au contexte de la requête.
Symfony fournit aussi une classe Response : une simple représentation PHP du message d'une réponse HTTP. Cela permet à votre application d'utiliser une interface orientée objet pour construire la réponse qui doit être retournée au client:
Listing 1-7 1 use Symfony\Component\HttpFoundation\Response;
2 $response = new Response();
4 $response->setContent('
Hello world!
');
5 $response->setStatusCode(200);
6 $response->headers->set('Content-Type', 'text/html');
8 // affiche les entêtes HTTP suivies du contenu
9 $response->send();
Si Symfony n'offrait rien d'autre, vous devriez néanmoins déjà avoir en votre possession une boîte à outils pour accéder facilement aux informations de la requête et une interface orientée objet pour créer la réponse. Bien que vous appreniez les nombreuses et puissantes fonctions de Symfony, gardez à l'esprit que le but de votre application est toujours d'interpréter une requête et de créer la réponse appropriée basée sur votre logique applicative.
Les classes Request et Response font partie d'un composant autonome inclus dans Symfony appelé HttpFoundation. Ce composant peut être utilisé de manière entièrement indépendante de
Symfony et fournit aussi des classes pour gérer les sessions et les uploads de fichier.
Le Parcours de la Requête à la Réponse
Comme HTTP lui-même, les objets Request et Response sont assez simples. La partie difficile de la création d'une application est d'écrire ce qui vient entre les deux. En d'autres termes, le réel travail commence lors de l'écriture du code qui interprète l'information de la requête et crée la réponse.
Votre application fait probablement beaucoup de choses comme envoyer des emails, gérer des soumissions de formulaires, enregistrer des choses dans une base de données, délivrer des pages HTML et protéger du contenu de façon sécurisée. Comment pouvez-vous vous occuper de tout cela tout en conservant votre code organisé et maintenable ?
Symfony a été créé pour résoudre ces problématiques afin que vous n'ayez pas à le faire vous-même.
Le Contrôleur Frontal
Traditionnellement, les applications étaient construites de telle sorte que chaque « page » d'un site avait son propre fichier physique:
Listing 1-8 1
Il y a plusieurs problèmes avec cette approche, ce qui inclut la non-flexibilité des URLs (que se passaitil si vous souhaitiez changer en sans que tous vos liens existants ne cessent de fonctionner ?) et le fait que chaque fichier doive manuellement inclure tout un ensemble de fichiers coeurs pour que la sécurité, les connexions à la base de données et le « look » du site puissent rester cohérents.
Une bien meilleure solution est d'utiliser un simple fichier PHP appelé contrôleur frontal: qui s'occupe de chaque requête arrivant dans votre application. Par exemple:
exécute
exécute
exécute
En utilisant la fonction mod_rewrite d'Apache (ou son équivalent avec d'autres serveurs web), les URLs peuvent être facilement réécrites afin de devenir simplement /, /contact et /blog.
Maintenant, chaque requête est gérée exactement de la même façon. Plutôt que d'avoir des URLs individuelles exécutant des fichiers PHP différents, le contrôleur frontal est toujours exécuté, et le routage (« routing ») des différentes URLs vers différentes parties de votre application est effectué en interne. Cela résoud les deux problèmes de l'approche originale. Presque toutes les applications web modernes font ça - incluant les applications comme WordPress.
Rester Organisé
Dans votre contrôleur frontal, vous devez déterminer quelle portion de code doit être exécuté et quel est le contenu qui doit être retourné. Vous le savoir, vous allez devoir inspecter l'URI entrante et exécuter les différentes parties de votre code selon cette valeur. Cela peut rapidement devenir moche:
Listing 1-9 1 //
2 use Symfony\Component\HttpFoundation\Request;
3 use Symfony\Component\HttpFoundation\Response;
4 $request = Request::createFromGlobals();
5 $path = $request->getPathInfo(); // Le chemin de l'URI demandée 6
7 if (in_array($path, array('', '/'))) {
8 $response = new Response('Bienvenue sur le site.');
9 } elseif ($path == '/contact') {
10 $response = new Response('Contactez nous');
11 } else {
12 $response = new Response('Page non trouvée.', 404);
13 }
14 $response->send();
Résoudre ce problème peut être difficile. Heureusement, c'est exactement ce pourquoi Symfony a été conçu.
Le Déroulement d'une Application Symfony
Quand vous laissez Symfony gérer chaque requête, la vie est beaucoup plus facile. Symfony suit un schéma simple et identique pour toutes les requêtes :
Les requêtes entrantes sont interprétées par le routing et passées aux fonctions des contrôleurs qui retournent des objets Response.
Chaque « page » de votre site est définie dans un fichier de configuration du routing qui relie différentes URLs à différentes fonctions PHP. Le travail de chaque fonction PHP, appelée contrôleur, est de créer puis retourner un objet Response, construit à partir des informations de la requête, à l'aide des outils mis à disposition par le framework. En d'autres termes, le contrôleur est le lieu où votre code se trouve : c'est là que vous interprétez la requête et que vous créez une réponse. C'est si facile ! Revoyons cela :
- Chaque requête exécute un même et unique fichier ayant le rôle de contrôleur frontal;
- Le système de routing détermine quelle fonction PHP doit être exécutée en se basant sur les informations provenant de la requête et la configuration de routage que vous avez créé;
- La fonction PHP correcte est exécutée, là où votre code crée et retourne l'objet Response approprié.
Une Requête Symfony en Action
Sans aller trop loin dans les détails, voyons ce procédé en action. Supposons que vous vouliez ajouter une page /contact à votre application Symfony. Premièrement, commencez par ajouter une entrée pour /contact dans votre fichier de configuration du routing:
Listing 1-10 1 # 2 contact:
3 path: /contact
4 defaults: { _controller: AcmeDemoBundle:Main:contact }
Cet exemple utilise YAML pour définir la configuration de routage. Cette dernière peut aussi être écrite dans d'autres formats comme XML ou PHP.
Lorsque quelqu'un visite la page /contact, il y a correspondance avec cette route, et le contrôleur spécifié est exécuté. Comme vous l'apprendrez dans le chapitre sur le routage, la chaîne de caractères AcmeDemoBundle:Main:contact est une syntaxe raccourcie qui pointe vers une méthode PHP spécifique contactAction dans la classe appelée MainController:
Listing 1-11 1 // 2 namespace Acme\DemoBundle\Controller;
3
4 use Symfony\Component\HttpFoundation\Response;
5
6 class MainController
7 {
8 public function contactAction()
9 {
10 return new Response('
Contactez nous!
');
11 }
12 }
Dans cet exemple très simple, le contrôleur crée simplement un objet Responsecontenant l'HTML "
Contactez nous!
". Dans le chapitre Contrôleur, vous allez apprendre comment un contrôleur peut retourner des templates, permettant à votre code de « présentation » (c-a-d du code qui retourne du HTML) de se trouver dans un fichier de template séparé. Cela libère le contrôleur et lui permet de s'occuper seulement des choses complexes : interagir avec la base de données, gérer les données soumises, ou envoyer des emails.
Symfony2: Construisez votre application, pas vos outils
Vous savez maintenant que le but de toute application est d'interpréter chaque requête entrante et de créer une réponse appropriée. Avec le temps, une application grandit et il devient plus difficile de garder le code organisé et maintenable. Invariablement, les mêmes tâches complexes reviennent encore et toujours : persister des éléments dans la base de données, afficher et réutiliser des templates, gérer des soumissions de formulaires, envoyer des emails, valider des entrées d'utilisateurs et gérer la sécurité.
La bonne nouvelle est qu'aucun de ces problèmes n'est unique. Symfony fournit un framework rempli d'outils qui vous permettent de construire votre application, mais pas vos outils. Avec Symfony2, rien ne vous est imposé : vous êtes libre d'utiliser le framework Symfony en entier, ou juste une partie de Symfony indépendamment.
Outils Autonomes: Les Composants Symfony2
Donc qu'est-ce que Symfony2? Premièrement, Symfony2 est une collection de plus de vingt bibliothèques indépendantes qui peuvent être utilisées dans n'importe quel projet PHP. Ces bibliothèques, appelées les Composants Symfony2, contiennent des choses utiles en toute situation, quelle que soit la manière dont votre projet est développé. Pour en nommer quelques-unes :
- • HttpFoundation - Contient les classes Request et Response, ainsi que d'autres classes pour la gestion des sessions et des uploads de fichiers;
- • Routing - Un puissant et rapide système qui vous permet de lier une URI spécifique (par exemple: /contact) à l'information lui permettant de savoir comment gérer cette requête (par exemple: exécute la méthode contactAction());
- • Form- Un framework complet et flexible pour la création de formulaires et la gestion de la soumission de ces derniers;
- • ValidatorUn système permettant de créer des règles à propos de données et de valider ou non les données utilisateurs soumises suivant ces règles;
- • ClassLoader Une bibliothèque pour le chargement automatique (« autoloading ») qui permet aux classes PHP d'être utilisées sans avoir besoin d'inclure (« require ») manuellement les fichiers contenant ces dernières;
- • Templating Une boîte à outils pour afficher des templates, gérer leur héritage (c-a-d qu'un template est décoré par un layout) et effectuer d'autres tâches communes aux templates;
- • Security- Une puissante bibliothèque pour gérer tous les types de sécurité dans une application;
- • TranslationUn framework pour traduire les chaînes de caractères dans votre application.
Chacun de ces composants est découplé et peut être utilisé dans n'importe quel projet PHP, que vous utilisiez le framework Symfony2 ou non. Chaque partie est faite pour être utilisée si besoin est, et remplacée quand cela est nécessaire.
La Solution Complète: Le Framework Symfony2
Donc finalement, qu'est-ce que le Framework Symfony2 ? Le Framework Symfony2 est une bibliothèque PHP qui accomplit deux tâches distinctes :
- Fournir une sélection de composants (les Composants Symfony2) et des bibliothèques tierces (ex Swiftmailer18 pour envoyer des emails);
- Fournir une configuration et une bibliothèque « colle » qui lie toutes ces pièces ensembles.
Le but du framework est d'intégrer plein d'outils indépendants afin de fournir une expérience substantielle au développeur. Même le framework lui-même est un bundle Symfony2 (c-a-d un plugin) qui peut être configuré ou remplacé entièrement.
Symfony2 fournit un puissant ensemble d'outils pour développer rapidement des applications web sans pour autant s'imposer à votre application. Les utilisateurs normaux peuvent commencer rapidement à développer en utilisant une distribution Symfony2, ce qui fournit un squelette de projet avec des paramètres par défaut. Pour les utilisateurs avancés, le ciel est la seule limite.
Chapter 2
Symfony2 versus PHP pur
Pourquoi est-ce que Symfony2 est mieux que simplement ouvrir un fichier et écrire du PHP pur?
Si vous n'avez jamais utilisé un framework PHP, que vous n'êtes pas familier avec la philosophie MVC, ou simplement que vous vous demandez pourquoi il y a tant d'agitation autour de Symfony2, ce chapitre est pour vous. Au lieu de vous dire que Symfony2 vous permet de développer plus rapidement de meilleures applications qu'en PHP pur, vous allez le voir de vos propres yeux.
Dans ce chapitre, vous allez écrire une application simple en PHP, puis refactoriser le code afin d'en améliorer l'organisation. Vous voyagerez dans le temps, en comprenant les décisions qui ont fait évoluer le développement web au cours de ces dernières années.
D'ici la fin, vous verrez comment Symfony peut vous épargner les tâches banales et vous permet de reprendre le contrôle de votre code.
Un simple blog en PHP
Dans ce chapitre, vous bâtirez une application de blog en utilisant uniquement du code PHP. Pour commencer, créez une page qui affiche les billets du blog qui ont été sauvegardés dans la base de données.
Écrire en pur PHP est « rapide et sale » :
C'est rapide à écrire, rapide à exécuter et, comme votre application évoluera, impossible à maintenir. Il y a plusieurs problèmes qui doivent être résolus :
- • aucune gestion d'erreur : Que se passe-t-il si la connexion à la base de données échoue?
- • mauvaise organisation : si votre application évolue, ce fichier deviendra de moins en moins maintenable. Où devrez-vous mettre le code qui traite la soumission d'un formulaire? Comment pourrez-vous valider les données? Où devrez-vous mettre le code qui envoie des courriels?
- • Difficulté de réutiliser du code : puisque tout se trouve dans un seul fichier, il est impossible de réutiliser des parties de l'application pour d'autres pages du blog.
Un autre problème non mentionné ici est le fait que la base de données est liée à MySQL. Même si le sujet n'est pas couvert ici, Symfony intègre Doctrine, une bibliothèque dédiée à l'abstraction des base de données et au mapping objet-relationnel.
Retroussons-nous les manches et résolvons ces problèmes ainsi que d'autres.
Isoler la présentation
Le code sera mieux structuré en séparant la logique « applicative » du code qui s'occupe de la « présentation » HTML :
Listing 2-2 1
Par convention, le fichier qui contient la logique applicative () est appelé « contrôleur ». Le terme contrôleur est un mot que vous allez entendre souvent, quel que soit le langage ou le framework utilisé. Il fait simplement référence à votre code qui traite les entrées de l'utilisateur et prépare une réponse.
Dans notre cas, le contrôleur prépare les données de la base de données et inclut ensuite un template pour présenter ces données. Comme le contrôleur est isolé, vous pouvez facilement changer uniquement le fichier de template si vous désirez afficher les billets du blog dans un autre format (par exemple pour un format JSON).
Isoler la logique applicative
Pour l'instant, l'application ne contient qu'une seule page. Mais que faire si une deuxième page a besoin d'utiliser la même connexion à la base de données, ou le même tableau de billets du blog? Refactorisez le code pour que le comportement principal et les fonctions d'accès aux données de l'application soient isolés dans un nouveau fichier appelé :
Vous avez maintenant une méthode qui permet la réutilisation du layout. Malheureusement, pour accomplir cela, vous êtes forcé d'utiliser des fonctions PHP (ob_start(), ob_get_clean()) dans le template. Symfony utilise un composant de Templates qui permet d'accomplir ce résultat proprement et facilement. Vous le verrez en action bientôt.
Ajout d'une page pour afficher un billet
La page « liste » a maintenant été refactorisée afin que le code soit mieux organisé et réutilisable. Pour le prouver, ajoutez une page qui va afficher un billet identifié par un paramètre de requête id.
Pour commencer, créez une fonction dans le fichier qui récupère un seul billet du blog en fonction d'un id passé en paramètre:
Listing 2-8 1 //
2 function get_post_by_id($id)
3 {
4 $link = open_database_connection();
5
6 $id = intval($id);
7 $query = 'SELECT date, title, body FROM post WHERE id = '.$id;
8 $result = mysql_query($query);
9 $row = mysql_fetch_assoc($result);
10 close_database_connection($link);
13 return $row;