1. Introduction▲
Félicitations ! En voulant apprendre Symfony, vous êtes sur le bon chemin pour être un développeur Web productif, bien équipé et capable d'accroître votre popularité sur Internet.
Symfony est conçu pour revenir aux bases : développer des outils vous permettant de programmer plus vite et construire des applications plus robustes. Tout en restant en arrière-plan, Symfony est conçu avec les meilleurs concepts de plusieurs technologies : les outils et thématiques que vous allez apprendre représentent les efforts de milliers de personnes, depuis de nombreuses années. En d'autres termes, vous n'allez pas juste apprendre « Symfony », vous allez apprendre les fondamentaux du Web, les meilleures pratiques de programmation et utiliser de nombreuses nouvelles bibliothèques incroyables, à l'intérieur ou indépendamment de Symfony. Donc, soyez prêt.
Fidèle à la philosophie de Symfony, ce chapitre va commencer par vous expliquer les concepts fondamentaux communs à la programmation Web : HTTP. Indépendamment de votre expérience ou de votre langage de programmation préféré, ce chapitre est un indispensable pour tout le monde.
2. HTTP est simple▲
HTTP (Hypertext Transfer Protocol pour les geeks) est un langage texte qui permet à deux machines de communiquer entre elles. Quand vous regardez la dernière illustration vidéo de xkcd, la conversation (approximative) suivante se déroule :
Et bien que le langage réel utilisé est un peu plus formel, il reste très simple. HTTP est le terme utilisé pour décrire ce langage simple basé sur du texte. Peu importe comment vous programmez sur le Web, l'objectif de votre serveur sera toujours de comprendre de simples requêtes texte, et de retourner de simples réponses texte.
Symfony est conçu à partir de cette réalité. Que vous en soyez conscients ou non, HTTP est quelque chose que vous utilisez tous les jours. Avec Symfony, vous allez apprendre à le maîtriser.
2-1. Étape 1 : le client envoie une requête▲
Toute conversation sur le Web commence par une requête. Une requête est un message texte créé par un client (exemple : un navigateur, une application de Smartphone, etc.) dans un format spécial connu sous le nom de HTTP. Le client envoie cette requête au serveur et en attend la réponse.
Jetez un œil à la première partie de l'interaction (la requête) entre un navigateur et le serveur Web xkbd :
|
En langage HTTP, cette requête HTTP devrait ressembler à quelque chose comme suit :
2.
3.
4.
GET / HTTP/1.1
Host: xkcd.com
Accept: text/html
User-Agent: Mozilla/5.0 (Macintosh)
Ce message, aussi simple soit-il, communique tout ce qui est nécessaire à propos de la ressource que le client a demandée. La première ligne de la requête HTTP est la plus importante et contient deux éléments : la méthode HTTP (GET) et l'URL (/).
L'URI (par exemple : /, ; /contact ; etc.) est l'adresse unique ou l'emplacement qui identifie la ressource que le client demande. La méthode HTTP (par exemple : GET) définit ce que vous voulez faire avec la ressource. Les méthodes HTTP (aussi connues par le terme verbs) définissent le peu d'actions communes possibles que les clients peuvent effectuer sur les ressources - les méthodes HTTP les plus utilisées sont :
GET |
Récupère la ressource sur le serveur |
POST |
Crée une ressource sur le serveur |
PUT |
Met à jour la ressource sur le serveur |
DELETE |
Supprime la ressource du serveur |
Avec ceci en tête, vous pouvez imaginer à quoi ressemble une requête pour supprimer une entrée spécifique de blog, par exemple :
DELETE /blog/15 HTTP/1.1
Il y a actuellement neuf méthodes définies dans les spécifications HTTP, mais la plupart ne sont pas beaucoup utilisées ou prises en charge. En réalité, la plupart des navigateurs modernes supportent uniquement POST et GET dans les formulaires HTML. Diverses autres sont par contre prises en charge dans XMLHttlpRequets, aussi bien que dans le composant de routage de Symfony.
En supplément à la première ligne, une requête HTTP contient invariablement d'autres lignes d'informations nommées en-têtes de requête. Les en-têtes peuvent fournir plusieurs informations sur l'hôte dont les ressources sont demandées (indiquées par le paramètre Host), les formats de réponse que le client accepte (indiqués par le paramètre Accept) et l'application que le client utilise pour effectuer la requête (indiquée par le paramètre User-Agent). Beaucoup d'autres paramètres d'en-têtes existent et peuvent être trouvés sur la page Wikipédia de la liste des en-têtes HTTP.
2-2. Étape 2 : le serveur retourne une réponse▲
Une fois que le serveur a reçu la requête, il sait exactement quelle ressource le client a souhaitée (via l'URI) et ce qu'il veut en faire (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érons la réponse du serveur Web xkcd :
Traduite en HTTP, la réponse retournée au navigateur sera quelque chose comme ceci :
2.
3.
4.
5.
6.
7.
8.
HTTP/1.1 200 OK
Date: Sat, 02 Apr 2011 21:05:05 GMT
Server: lighttpd/1.4.19
Content-Type: text/html
<html>
<!-- ... HTML pour l'illustration video xkcd -->
</html>
La réponse HTTP contient la ressource demandée (le contenu HTML dans ce cas), ainsi que d'autres informations relatives à la réponse. La première ligne est particulièrement importante et contient le code du statut de la réponse HTML (200 dans ce cas). Le code du statut communique le résultat global du retour au client. La requête a-t-elle abouti ? Y a-t-il eu une erreur ? Il existe plusieurs codes de statuts différents pour indiquer un succès, une erreur, ou que le client doit faire quelque chose (par exemple : redirection vers une autre page). Une liste complète des codes de statut HTTP peut être consultée sur Wikipédia.
Comme la requête, une réponse HTTP contient des informations additionnelles connues sous le nom d'en-têtes HTTP. Par exemple, Content-Type est un élément d'en-tête de réponse HTTP important. Le corps d'une même ressource peut être retourné sur plusieurs types de formats tels que HTML, XML ou JSON, et l'en-tête Content-Type utilise les types médias internet tels que text/html pour indiquer au client le format du contenu retourné. Vous pouvez consulter la liste des types de formats médias les plus utilisés sur IANA.
Plusieurs autres en-têtes existent, dont certains sont très puissants. Par exemple, certains en-têtes peuvent être utilisés pour créer un puissant système de cache.
3. Requêtes, réponses, et programmation Web▲
Ce système de conversation requêtes-réponses est le processus fondamental qui dirige les communications sur le Web. Et aussi important et puissant que soit ce processus, il est inéluctablement simple.
Le fait le plus important est celui-ci : indépendamment du langage que vous utilisez, du type d'applications que vous créez (web, mobile, API JSON) ou la philosophie de programmation que vous suivez, le but final d'une application est toujours de comprendre chaque requête puis de créer et retourner un résultat approprié.
Symfony est architecturé pour correspondre à cette réalité.
Pour en apprendre plus sur les spécifications HTTP, lisez la RFC du HTTP 1.1 (version anglaise originale) ou HTTP Bis, qui est un effort considérable pour clarifier les spécifications originelles. L'extension Firefox Live HTTP Headers est un puissant outil pour contrôler les en-têtes de requêtes et de réponses durant la navigation.
4. Requêtes et réponses en HTTP▲
Comment interagir avec la « requête » et créer une « réponse » quand on utilise PHP ? En réalité, PHP vous fait un peu abstraction de l'ensemble du processus :
Aussi étrange que cela paraisse, cette petite application va prendre des informations depuis la requête HTTP et les utiliser pour créer une réponse HTTP. Au lieu de parser le message de requête HTTP brute, PHP prépare des variables superglobales telles que $_SERVER et $_GET qui contiennent toutes les informations de la requête. De façon similaire, plutôt que de retourner le texte de réponse formatée HTTP, vous pouvez utiliser la fonction header() pour créer les en-têtes de réponse et simplement présenter le contenu courant qui sera une partie du message de réponse. PHP va créer une vraie réponse HTTP et la retourner au client :
2.
3.
4.
5.
6.
7.
HTTP/1.1 200 OK
Date: Sat, 03 Apr 2011 02:14:33 GMT
Server: Apache/2.2.17 (Unix)
Content-Type: text/html
L'URI demandée est : /testing?foo=symfony
La valeur du paramètre "foo" est : symfony
5. 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 les requêtes et réponses HTTP de façon plus simple.
5-1. L'objet requête de Symfony▲
La classe « Request » est une simple représentation orientée objet de la requête message HTTP. Avec elle, vous pouvez récupérer toutes les informations utiles de la requête :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
use Symfony\Component\HttpFoundation\Request;
$request
=
Request::
createFromGlobals();
// L'URI va être demandée (ex. : /about)
$request
->
getPathInfo();
// récupère respectivement les variables GET et POST
$request
->
query
->
get('
foo
'
);
$request
->
request->
get('
bar
'
,
'
valeur par défaut si bar n
\'
existe pas
'
);
// récupère les variables SERVER
$request
->
server->
get('
HTTP_HOST
'
);
// récupère une instance de fichier uploadé identifié par foo
$request
->
files->
get('
foo
'
);
// récupère une valeur de COOKIE
$request
->
cookies->
get('
PHPSESSID
'
);
// récupère un en-tête de requête HTTP, avec des clés minuscules normalisées
$request
->
headers->
get('
host
'
);
$request
->
headers->
get('
content_type
'
);
$request
->
getMethod();
// GET, POST, PUT, DELETE, HEAD
$request
->
getLanguages();
// un tableau des langages que le client accepte
Comme un bonus, la classe « Request » effectue beaucoup de tâches en arrière-plan pour lesquelles vous n'aurez plus à vous préoccuper. Par exemple, la méthode isSecure() vérifie les trois différentes valeurs dans PHP qui indiquent si l'utilisateur se connecte via une connexion sécurisée (par exemple : HTTPS).
ParametersBags et attributs de requête
Comme vu ci-dessus, les variables $_GET et $_POST sont respectivement accessibles via la requête publique et les propriétés de requête. Chacun de ces objets est un objet ParameterBag, lesquels ont des méthodes comme get(), has(), all() et plus. En fait, chaque propriété publique utilisée dans l'exemple précédent est une instance particulière de ParameterBag.
La classe « Request » a également une propriété publique attributes, laquelle contient des données spéciales relatives au fonctionnement de l'application en interne. Pour le framework Symfony, les attributes contiennent les valeurs retournées par la route correspondante comme _controller, id (si vous avez un {id} wildcard), et même le nom de la route correspondante (_route). La propriété attributes existe entièrement pour être un emplacement où vous pouvez préparer et stocker des informations spécifiques au contexte à propos de la requête.
Symfony fournit également une classe « Response » : une simple représentation PHP d'un message de réponse HTTP. Ceci permet à votre application d'utiliser une interface orientée objet pour construire la réponse qui doit être retournée au client :
2.
3.
4.
5.
6.
7.
8.
9.
10.
use Symfony\Component\HttpFoundation\Response;
$response
=
new Response();
$response
->
setContent('
<html><body><h1>Hello world!</h1></body></html>
'
);
$response
->
setStatusCode(Response::
HTTP_OK);
$response
->
headers->
set('
Content-Type
'
,
'
text/html
'
);
// affiche les en-têtes HTTP suivis par le contenu
$response
->
send();
Il existe aussi des classes spéciales pour faciliter la création de certains types de réponses :
- JsonResponse ;
- BinaryFileResponse (pour les fichiers de streaming et les fichiers en téléchargement) ;
- StreamedResponse (pour le streaming des grosses réponses).
Les classes « Request » et « Response » sont des éléments du composant standalone appelé « symfony/http-foundation » qui peut être utilisé pour tout projet PHP. C'est un composant qui contient des classes pour gérer des sessions, l'upload des fichiers et plus encore.
Si Symfony n'offrait rien d'autre, vous auriez déjà un toolkit pour facilement accéder aux informations de requête et à une interface orientée objet pour créer les réponses. Alors même que vous apprenez les nombreuses puissantes fonctions dans Symfony, gardez en tête que le but de votre application est toujours d'interpréter une requête et créer la réponse appropriée basée sur la logique de votre application.
6. Le trajet de la requête à la réponse▲
Comme HTTP lui-même, les objets Request et Response sont assez simples. La partie la plus difficile de l'implémentation d'une application est d'écrire ce qui se passe entre ces deux objets. En d'autres termes, le vrai travail commence à l'écriture du code qui interprète la requête et crée la réponse.
Votre application fait probablement plusieurs choses, comme envoyer des mails, gérer la soumission de formulaires, insérer des informations dans une base de données, faire du rendu de pages HTML et protéger le contenu avec de la sécurité. Comment pouvez-vous gérer tout cela et garder toujours votre code organisé et maintenable ?
Symfony a été créé pour résoudre ces équations pour que vous n'ayez plus à vous en soucier.
6-1. Le contrôleur frontal▲
Traditionnellement, les applications sont construites pour qu'à chaque « page » du site corresponde un fichier :
2.
3.
index.php
contact.php
blog.php
Il y a plusieurs problèmes avec cette approche, incluant la non-flexibilité des URL (par exemple, comment changer blog.php en news.php sans casser tous vos liens ?) et le fait que chaque fichier doit inclure manuellement un ensemble de fichiers core pour que la sécurité, les connexions de base de données, et le « look » du site puissent rester consistants.
Une bien meilleure solution est d'utiliser un contrôleur frontal : un seul fichier qui gère toutes les requêtes provenant de votre application. Par exemple :
/index.php |
exécute index.php |
/index.php/contact |
exécute index.php |
/index.php/blog |
exécute index.php |
En utilisant le module Apache mod_rewrite (ou l'équivalent avec un autre serveur Web), les URL peuvent être facilement nettoyées pour être simplement : /, /contact et /blog.
Aujourd'hui, toutes les requêtes sont gérées exactement de la même façon, à la place d'URL individuelles, exécutant différents fichiers PHP, le contrôleur frontal est toujours exécuté, et le routage des différentes URL vers les différentes parties de votre application est fait en interne. Ceci résout les deux problèmes avec l'approche originelle. Pratiquement toutes les applications Web modernes fonctionnent de cette façon, comme WordPress.
6-2. Rester organisé▲
Dans votre contrôleur frontal, vous devez déterminer quel code devrait être exécuté et quel devrait être le contenu retourné. Pour cela, vous devrez contrôler l'URI entrante et exécuter différentes parties de votre code en fonction de cette valeur. Ceci peut être rapidement laid :
// index.php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request
=
Request::
createFromGlobals();
$path
=
$request
->
getPathInfo();
// Le chemin de l'URI demandée
if (in_array($path
,
array(''
,
'
/
'
))) {
$response
=
new Response('
Bienvenue sur la homepage.
'
);
}
elseif ('
/contact
'
===
$path
) {
$response
=
new Response('
Contactez-nous
'
);
}
else {
$response
=
new Response('
Page non trouvée.
'
,
Response::
HTTP_NOT_FOUND);
}
$response
->
send();
Résoudre ce problème peut être difficile. Heureusement, c'est exactement ce pour quoi Symfony a été conçu.
7. Les flux internes dans une application Symfony▲
Laisser à Symfony la latitude de gérer chaque requête, c'est vous simplifier la vie. Symfony suit le même modèle, très simple, pour chaque requête :
Les requêtes entrantes sont interprétées par le composant de routage avant de passer aux fonctions PHP (contrôleur) qui retournent les objets Response.
Chaque « page » de votre site est définie dans un fichier de configuration de routage qui mappe les différentes URL aux différentes fonctions PHP. Chaque fonction PHP, appelée contrôleur, a pour action de recueillir les informations de la requête - et de nombreux autres outils fournis par Symfony - pour créer et retourner un objet Response. En d'autres termes, le contrôleur, c'est là où se situe ce que vous programmez : c'est là où vous interprétez la requête et créez la réponse.
C'est très facile ! Pour récapituler :
- chaque requête exécute un même fichier (nommé contrôleur frontal) ;
- le contrôleur frontal démarre (boote) sur Symfony et lui transmet toutes les requêtes ;
- le système de routage établit la correspondance entre l'URL entrante et la route spécifique, puis retourne les informations relatives à la route, dont le contrôleur (la fonction PHP) qui devra être exécuté ;
- le contrôleur (la fonction PHP) est exécuté : c'est là que votre code crée et retourne l'objet approprié Response ;
- les en-têtes HTTP et le contenu de l'objet Response sont retournés au client.
8. Une requête Symfony en action▲
Sans se noyer dans trop de détails, voici le processus en action. Supposez que vous vouliez ajouter une page /contact à votre application Symfony. Premièrement, commencez par ajouter une entrée pour /contact dans le fichier de configuration de routage :
YAML :
2.
3.
4.
# app/config/routing.yml
contact
:
path
:
/contact
defaults
:
{
_controller
:
AppBundle
:
Main
:
contact }
XML :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
<!-- app/config/routing.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes
xmlns
=
"http://symfony.com/schema/routing"
xmlns
:
xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi
:
schemaLocation
=
"http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd"
>
<route
id
=
"contact"
path
=
"/contact"
>
<default
key
=
"_controller"
>
AppBundle:Main:contact</default>
</route>
</routes>
PHP :
Quand quelqu'un visite la page /contact, cette route est adaptée et le contrôleur spécifié est exécuté. Comme vous allez l'apprendre dans le chapitre routage, la chaîne AppBundle:Main:contact est une syntaxe courte qui pointe vers une méthode PHP spécifique contactAction dans une classe nommée MainController :
Dans cet exemple, le contrôleur crée simplement un objet Response avec le code HTML
<h1>Contact us!</h1>
Dans le chapitre sur le contrôleur, vous apprendrez comment un contrôleur peut interpréter des templates, autorisant votre code de « présentation » (c'est-à-dire tout ce qui génère du HTML) à résider dans un fichier de template séparé. Ceci libère le contrôleur et lui permet de ne se préoccuper que du noyau dur : interagir avec la base de données, gérer les données soumises, ou envoyer des mails.
9. Symfony : créer 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. Puisqu'une application croît, il devient plus difficile de garder votre code organisé et maintenable.
Invariablement, les mêmes tâches complexes continuent à venir encore et encore : rendre persistantes les choses dans la base de données, interpréter et réutiliser des templates, gérer des soumissions de formulaire, envoyer des mails, validation utilisateurs (entrées et gestion sécurité).
La bonne nouvelle, c'est qu'aucun de ces problèmes n'est unique. Symfony fournit un framework plein d'outils qui permettent de créer votre application, pas vos outils. Avec Symfony, rien ne vous est imposé ; vous êtes libre d'utiliser le framework complet ou seulement une petite partie de celui-ci.
9-1. Les outils autonomes : les composants de Symfony▲
Donc qu'est-ce que Symfony ? Tout d'abord Symfony est une collection de plus de vingt bibliothèques indépendantes qui peuvent être utilisées dans tout projet PHP. Ces bibliothèques, appelés les composants Symfony, contiennent quelque chose d'utile pour presque toute situation, indépendamment de comment votre projet est développé. Pour en nommer quelques-uns :
HttpFoundation
Contient les classes Request et Response, tout comme d'autres classes pour gérer les sessions et les uploads de fichiers.
Routing
Puissant et rapide système vous autorisant à mapper une URI spécifique (ex. : /contact) à certaines informations à propos de comment cette requête doit être gérée (par exemple : exécuter la méthode contactAction()).
Form
Un framework complet et flexible pour créer des formulaires et gérer leur soumission.
Validator
Un système pour créer des règles relatives aux données, qui consiste en la validation de ces données selon que les valeurs soumises par l'utilisateur respectent ces règles ou pas.
Templating
Un toolkit pour faire du rendu de template, gérer leur héritage (ex. : un template peut être enrichi avec un layout) et effectuer d'autres tâches standards sur les templates.
Security
Une bibliothèque puissante pour gérer tout type de sécurité dans une application.
Translation
Un framework pour traduire des chaînes dans votre application.
Chacun de ces composants est découplé et peut être utilisé dans n'importe quel projet PHP, indépendamment ou non de l'ensemble du framework Symfony. Chaque partie est faite pour être utilisée si besoin et remplacée quand nécessaire.
9-2. La solution complète : le framework Symfony▲
Donc qu'est-ce que le framework Symfony ? C'est une bibliothèque PHP qui accomplit deux tâches distinctes :
- Fournir un ensemble de composants (exemple : les composants Symfony) et des bibliothèques tierces (ex. : Swift Mailer) pour l'envoi de mails).
- Fournir une configuration modulable et une bibliothèque « à effet glue » qui attache toutes les pièces ensemble.
Le but du framework est d'intégrer plusieurs outils indépendants de façon à fournir une expérience utilisateur solide pour le développeur. Même le framework lui-même est un paquet Symfony (c'est-à-dire un plugin) qui peut être entièrement configuré ou remplacé.
Symfony fournit un ensemble d'outils puissants pour développer rapidement des applications Web sans s'imposer dans votre application. Les utilisateurs normaux peuvent commencer des développements rapidement en utilisant une distribution Symfony, laquelle fournit un squelette de projet avec des valeurs adaptées. Pour les utilisateurs avancés, seul le ciel est la limite.
Notes de la rédaction Developpez.com▲
Nous tenons à remercier F-leb pour sa relecture orthographique.