Symfony
Fonctionnement
Les bundles
Un bundle est un répertoire qui a une structure bien définie et qui peut héberger à peu près tout : des classes aux contrôleurs en passant par les ressources web (C'est une version amélirée des plugins).
Un bunble à la structure suivante :
. ├── Controller (Contient les contrôleurs du bundle) │ └── IndexController.php ├── DependencyInjection (Contient les injections de dépendance) ├── EventListener (Contient les listener qui vont se déclencher lors de certains évènements (ex: lors d’une requête)) ├── Resources (Contient les configurations du bundle (routes, services…)) │ ├── config │ │ └── routing.yml │ │ └── services.yml │ ├── public (Contient les fichiers css / js / images) │ ├── translations (Contient les traductions du bundle) │ └── views (Contient les vues du bundle qui sont appelées par les contrôleurs) │ └── index.html.twig ├── Services (Contient les services) └── Tests (Contient les tests)
Le routing et les configurations (yml, xml, php)
Le routing permet d’associer une URL à un contrôleur et à une action de celui-ci.
Il existe 4 formats d’écriture des fichiers de route:
- Les annotations
- Le Yaml
- Le XML
- Le PHP
Et 3 formats pour les fichiers de configuration:
- Le Yaml
- Le XML
- Le PHP
Voici un exemple de route écrit en Annotation :
// src/AppBundle/Controller/BlogController.php class BlogController extends Controller { /** * @Route("/blog/{culture}") */ public function showAction($culture) { // … } }
Voici un exemple de route écrit en Yaml :
# src/AppBundle/Resources/config/routing.yml blog_show: path: /blog/{culture} defaults: { _controller: AppBundle:Blog:show } requirements: culture: en|fr
Voici un exemple de route écrit en XML :
<!-- src/AppBundle/Resources/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="blog_show" path="/blog/{culture}"> <default key="_controller">AppBundle:Blog:show</default> </route> </routes>
Voici un exemple de route écrit en PHP :
// src/AppBundle/Resources/config/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog_show', new Route('/blog/{culture}', array('_controller' => 'AppBundle:Blog:show'))); return $collection;
Les annotations et le format Yaml sont les deux formats les plus utilisés dans Symfony de par leur syntaxe simple et lisible.
Les contrôleurs
Voici un exemple de contrôleur Symfony :
<?php namespace MyProject\BlogBundle\Controller; use MyProject\CoreBundle\Controller\Common\BaseController; use Doctrine\ORM\Query; use Symfony\Component\HttpFoundation\Request; class BlogController extends BaseController { /** * @Route("/article/{id}") */ public function articleAction(Request $request, $id) { $culture = $request->getLocale(); // Requête pour récupérer l'article (on appel le modèle) $article = $this->getDoctrine()->getManager()->getRepository("MyProjectBlogBundle:Article")->find($id); // On appel la vue return $this->render('MyProjectBlogBundle:article.html.twig', array('culture' => $culture, 'article' => $article)); } } ?>
Dans cet exemple de contôleur appel le modèle pour récupérer un article puis génère la vue en lui donnant les informations qu'elle a besoin.
Les vues (Twig / PHP)
Voici un exemple de vue Twig :
<!DOCTYPE html> <html> <head> <title> {% block title %} Blog :: {% endblock %} </title> {% block stylesheets %} <link rel="stylesheet" href="{{ asset('bundles/myprojectblog/css/jquery.css') }}" type="text/css" /> {% endblock %} {% block javascripts %} <script language="javascript" src="{{ asset('bundles/myprojectblog/js/jquery.js') }}"></script> {% endblock %} </head> <body> {% block content %}{% endblock %} {# END - BLOCK RESERVE AUX PLUGINS JQUERY UI UTILISANT LE CSS #} {% block endJavascripts %}{% endblock %} </body> </html>
Twig est un language simple qui permet l'héritage et l'imbracation. Sont language étant limité, cela permet d'éviter aux développeurs peu expérimentés d'écrire du code dans la partie template.
Dans l'exemple suivant, le code Twig redéfini ou surcharge les valeurs contenu dans les blocks du templates hérité (parent).
{% extends 'MyProjectBlogBundle::layout.html.twig' %} {% block title %} {{ parent() }} Article {% endblock %} {% block content %} <h2>{{ article.title|trans }}</h> <div class="content"> {% include('MyProjectBlogBundle:Article:content.html.twig') %} {% autoescape false %} {{ text }} {% endautoescape %} </div> {% endblock %}
Les modèles (yml, annotation, xml)
La partie modèle permet de définir la structure et les relations des objets par rapport à la base de données relationelle.
Elle peut être écrite sous forme d'annotation directement dans les classes des objets, en xml ou en Yaml.
Voici un exemple en Yaml :
MyProject\CoreBundle\Entity\User: type: entity repositoryClass: MyProject\CoreBundle\Repository\UserRepository table: user id: id: type: integer nullable: false unsigned: false id: true generator: strategy: IDENTITY fields: login: type: string nullable: false length: 255 manyToMany: profile: targetEntity: Profile inversedBy: user joinTable: name: lnk_user_profile joinColumns: name: user_id referencedColumnName: id inverseJoinColumns: name: profile_id referencedColumnName: id
Les formulaires
Les formulaires peuvent être crée de deux façon :
- Avec une classe
$mail = new Mail();
$form = $this->createForm(new MailType(), $mail); - Avec un builder
$form = $this->createFormBuilder()
->setAction($this->generateUrl('change_email_password'))
->add('email', 'repeated', array('type' => 'email'))
->getForm();
Les classes servent quand le formulaire est réutilisé plusieurs fois, ou lorsqu'il est lié à une entité.
Le builder est utile uniquement lorsque le formulaire est utilisé une seule fois, cela évite d'écrite trop de code.
Ce code doit être écrit dans le contrôleur et l'objet suivant doit être donnée à la vue pour qu'elle génère le formulaire :
$form->createView();
Pour afficher le formulaire voici un exemple de code à écrire dans la vue :
{{ form_start(form, {'action': path('new_mail', {'id': 10})}) }} {{ form_errors(form) }} <div id="email"> {{ form_label(form.email) }} {{ form_widget(form.email) }} {{ form_errors(form.email) }} </div> <div id="subject"> {{ form_label(form.subject) }} {{ form_widget(form.subject, {'attr': {'class': 'subject', 'title': 'Votre subjet'}) }} {{ form_errors(form.subject) }} </div> <nput type="submit" /> {{ form_end(form) }}
Les formulaires Symfony permettent :
- La génération des champs manquants
- La génération du token pour éviter les attaques CSRF
- La génération des validateurs HTML5
- La gestion des messages d’erreur
Afin de vérifier la valider d'un formulaire, Symfony met à disposition un sytème de validation :
$mail = new Mail(); $form = $this->createForm(new MailType(), $mail); $form->handleRequest($request); if ($form->isValid()) { // sauvegarde des éléments de votre formulaire qui ne sont pas mappés avec l'objet ... // sauvegarde de votre objet qui a été mis à jour par le formulaire $em = $this->getDoctrine()->getManager(); $em->persist($mail); $em->flush(); // redirige vers une autre page } // retourne sur la page du formulaire et affiche des messages d’erreur