Programmation PHP/Symfony

- Pour plus de détails voir : Programmation PHP avec Symfony.
Présentation[modifier | modifier le wikicode]
Symfony (parfois abrégé SF) est un cadriciel MVC libre écrit en PHP (> 5). En tant que framework, il facilite et accélère le développement de sites et d'applications Internet et Intranet. Il propose en particulier :
- Une séparation du code en trois couches, selon le modèle MVC, pour une plus grande maintenabilité et évolutivité.
- Des performances optimisées et un système de cache pour garantir des temps de réponse optimums.
- Le support de l'Ajax.
- Une gestion des URL parlantes (liens permanents), qui permet de formater l'URL d'une page indépendamment de sa position dans l'arborescence fonctionnelle.
- Un système de configuration en cascade qui utilise de façon extensive le langage YAML.
- Un générateur de back-office et un "démarreur de module" (scaffolding).
- Un support de l'I18N - Symfony est nativement multi-langue.
- Une architecture extensible, permettant la création et l'utilisation de composants, par exemple un mailer ou un gestionnaire de fichiers .css et .js (minification).
- Des bundles :
- Un templating simple, basé sur PHP et des jeux de "helpers", ou fonctions additionnelles pour les gabarits... Comme alternative au PHP, on peut aussi utiliser le moteur de templates Twig dont la syntaxe est plus simples.
- Une couche de mapping objet-relationnel (ORM) et une couche d'abstraction de données (cf. Doctrine et son langage DQL[1]).
Utilisations[modifier | modifier le wikicode]
Plusieurs autres projets notables utilisent Symfony, parmi lesquels :
- https://github.com/drupal/drupal : le système de gestion de contenu (CMS) Drupal.
- https://github.com/joomla/joomla-cms : le CMS Joomla.
- https://github.com/sulu/sulu : le CMS Sulu.
- https://github.com/Sylius/Sylius : Sylius, un CMS d'e-commerce.
- https://github.com/x-tools/xtools : Xtools, un compteur d'éditions des wikis.
Différences entre les versions[modifier | modifier le wikicode]
Depuis la version 4, des pages récapitulant les nouvelles fonctionnalités sont mises à disposition :
- https://symfony.com/blog/symfony-4-1-curated-new-features
- https://symfony.com/blog/symfony-4-2-curated-new-features
- https://symfony.com/blog/symfony-4-3-curated-new-features
- https://symfony.com/blog/symfony-4-4-curated-new-features
- https://symfony.com/blog/symfony-5-0-curated-new-features
- https://symfony.com/blog/symfony-5-1-curated-new-features
- https://symfony.com/blog/symfony-5-2-curated-new-features
- https://symfony.com/blog/symfony-5-3-curated-new-features
- https://symfony.com/blog/symfony-6-1-curated-new-features
- https://symfony.com/blog/symfony-6-2-curated-new-features
- https://symfony.com/blog/symfony-6-3-curated-new-features
Créer un projet[modifier | modifier le wikicode]

Vous trouverez sur la page dédiée Symfony 4 comment installer cette version sortie en 2017, et Symfony 3 ici. La v5 s'installe comme la v6, mais pour migrer de la v5 à la v6 il faut vérifier plusieurs choses.
Pour créer un nouveau projet sous Symfony 6, tapez la commande :
composer create-project "symfony/skeleton:^6" mon_projet
ou avec la commande "symfony" :
wget https://get.symfony.com/cli/installer -O - | bash symfony new mon_projet
Cette commande a pour effet la création d'un dossier contenant les bases du site web à développer.
Lancer le projet[modifier | modifier le wikicode]
On entend par cette expression le lancement d'un serveur web local pour le développement de l'application et le choix d'un hébergeur pour la déployer (autrement dit "la mettre en production").
Serveur web de développement[modifier | modifier le wikicode]
Symfony intègre un serveur web local qu'on peut lancer avec la commande (se placer dans le répertoire du projet auparavant) :
$ symfony server:start -d
En passant open:local
en argument de la commande symfony
, le projet s'ouvre dans un navigateur :
$ symfony open:local
Ou bien en utilisant le serveur web intégré à php
$ php -S localhost:8000 -t public
Serveur web de production[modifier | modifier le wikicode]
Pour le déploiement dans le monde "réel", il faut choisir un hébergeur web sur internet supportant PHP (nous l’appellerons "serveur web distant" pour le distinguer du précédent). Voici quelques exemples :
- https://www.lws.fr/hebergement_web.php
- https://www.hostinger.fr/hebergeur-web
- et surtout... https://symfony.com/cloud/
Autrement il est aussi possible d'installer un deuxième serveur web (autre que celui intégré à Symfony) sur sa machine pour se rendre compte du résultat final. Par exemple... Apache qui est très répandu chez les hébergeurs profesionnels. Il faudra alors ajouter un vhost et un nom de domaine dédiés au site Symfony[2][3]. Pour le test, le domaine peut juste figurer dans /etc/hosts
.
Le nom de domaine du site doit absolument rediriger vers le dossier /public. En effet, si on cherche à utiliser le site Symfony dans le sous-répertoire "public" d'un autre site, la page d'accueil s'affichera mais le routing ne fonctionnera pas.
Configurer le projet[modifier | modifier le wikicode]
Paramètres dev et prod[modifier | modifier le wikicode]
Les différences de configuration entre le site de développement et celui de production (par exemple les mots de passe) peuvent être définies de deux façons :
- Dans le dossier
config/packages
. config.yml contient la configuration commune aux sites, config_dev.yml celle de développement et config_prod.yml celle de production. - Via le composant Symfony/Dotenv (abordé au chapitre suivant).
Par exemple, on constate l'absence de la barre de débogage (web_profiler) par défaut en prod. Une bonne pratique serait d'ajouter au config_dev.yml :
web_profiler:
toolbar: true
intercept_redirects: false
twig:
cache: false
# Pour voir tous les logs dans la console shell (sans paramètre -vvv)
monolog:
handlers:
console:
type: console
process_psr_3_messages: false
channels: ['!event', '!doctrine', '!console']
verbosity_levels:
VERBOSITY_NORMAL: DEBUG
Les fichiers .yml contenant les variables globales sont dans app\config\.
Par exemple en SF2 et 3, le mot de passe et l'adresse de la base de données sont modifiables en éditant parameters.yml
(non versionné et créé à partir du parameters.yml.dist
). L'environnement de test passe par web/app_dev.php, et le mode debug y est alors activé par la ligne Debug::enable();
(testable avec %kernel.debug% = 1
).
Depuis SF4, il faut utiliser un fichier .env non versionné à la racine du projet, dont les lignes sont injectées ensuite dans les .yaml avec la syntaxe : '%env(APP_SECRET)%'
. Le mode debug est activé avec APP_DEBUG=1
dans ce fichier .env.
Les variables d'environnement du système d'exploitation peuvent remplacer celles des .env.
Commandes[modifier | modifier le wikicode]
Les commandes sont, avec les contrôleurs, les seuls points d'entrée permettant de lancer le programme.
La liste des commandes disponibles en console est visible avec :
php bin\console
Dans Symfony 2 c'était php app\console
.
Parmi les principales commandes natives au framework et à ses bundles, on trouve :
php bin/console list
: liste toutes les commandes du projet.php bin/console debug:router
: liste toutes les routes (URL) du site.php bin/console debug:container
: liste tous les services avec leurs alias (qui sont des instanciations des classes).php bin/console debug:container --parameters
: liste les paramètres.php bin/console debug:container --env-vars
: liste les variables d'environnement.php bin/console debug:autowiring --all
: liste tous les services automatiquement déclarés.php bin/console debug:config NomDuBundle
: liste tous les paramètres disponibles pour paramétrer un bundle donné.php bin/console cache:clear
: vide la mémoire cache du framework.php bin/console generate:bundle
: crée un bunble (surtout pour SF2).php bin/console generate:controller
: crée un contrôleur (en SF2).php bin/console doctrine:migrations:generate; chown 1001:1001 -R app/DoctrineMigrations
: génère un fichier vide de migration SQL ou DQL.php bin/console doctrine:migrations:list
: liste les noms des migrations disponibles (utiles car selon la configuration on doit les appeler par leur namespace ou juste par numéro).
Le mode le plus verbeux est obtenu en ajoutant "- vvv" après la commande.
Créer une commande[modifier | modifier le wikicode]
Lors du lancement d'une commande, on distingue deux types de paramètres[4] :
- Les arguments : non nommés
- Les options : nommées.
Exemple :
bin/console app:ma_commande argument1 --option1=test
#[AsCommand(name: 'app:ma_commande')]
class HelloWorldCommand extends Command
{
protected function configure(): void
{
$this
->addArgument(
'argument1',
InputArgument::OPTIONAL,
'Argument de test'
)
->addOption(
'option1',
null,
InputOption::VALUE_OPTIONAL,
'Option de test'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
echo 'Hello World! '.$input->getOption('option1').' '.$input->getArgument('argument1');
return self::SUCCESS;
}
}
NB : en SF < 6.1, remplacer l'attribut AsCommand par une propriété connue de la classe mère :
protected static $defaultName = 'app:ma_commande';
Pour définir un argument tableau, utiliser InputArgument::IS_ARRAY
et séparer les valeurs par un espace. Ex[5] :
bin/console app:my_command arg1.1 arg1.2 arg1.3
Contrôleurs[modifier | modifier le wikicode]
Les contrôleurs Symfony sont les classes qui définissent les opérations à réaliser quand on visite les pages du sites[6] : elles transforment une requête HTTP en réponse (JSON ou XML).
Par convention, leurs noms se terminent par Controller, les noms de leurs méthodes se terminent par "Action", et les URL qui provoquent leurs exécutions sont définies dans leurs annotations. L'exemple suivant affiche un texte quand on visite l'adresse "/" ou "/helloWorld" :
class HelloWorldController extends AbstractController
{
#[Route(path: '/', name: 'helloWorld')]
#[Route(path: '/helloWorld', name: 'helloWorld')]
public function indexAction(Request $request): Response
{
return new Response('Hello World!');
}
}
NB : en PHP < 8, remplacer l'attribut par une annotation :
/** * @Route("/", name="helloWorld") * @Route("/helloWorld") */
Retours[modifier | modifier le wikicode]
Ces méthodes peuvent déboucher sur plusieurs actions :
Response()
: affiche un texte, et facultativement un code HTTP en deuxième paramètre (ex : erreur 404).JsonResponse()
ou$this->json()
: affiche du JSON.RedirectResponse()
: renvoie vers une autre adresse. Si elle se trouve dans la même application, on peut aussi utiliser le$this->forward()
hérité du contrôleur abstrait.$this->redirect('mon_url')
: redirige à une autre adresse.$this->redirectToRoute('nom_de_la_route');
: redirige vers une route du site par son nom.$this->generateUrl('app_mon_chemin', []);
: redirige vers une URL relative (ajouterUrlGeneratorInterface::ABSOLUTE_URL
en paramètre 3 pour l'absolue, car il est àUrlGeneratorInterface::ABSOLUTE_PATH
par défaut dans SF3).$this->container->get('router')->generate('app_mon_chemin', ['paramètre' => 'mon_paramètre']);
.$this->render()
: affiche une page à partir d'un template, par exemple HTML ou Twig.
Flashbag[modifier | modifier le wikicode]
On peut aussi ajouter un bandeau de message temporaire en en-tête via :
$this->addflash('success', 'mon_message');
Le Twig peut les récupérer ensuite avec[7] :
{% for flashMessage in app.session.flashbag.get('success') %} {{ flashMessage }} {% endfor %}
En effet, ils sont stockés dans un Flashbag : un objet de session.
De plus, il en existe plusieurs types (chacun avec une couleur) : success, notice, info, warning, error.
Accès aux paramètres et services[modifier | modifier le wikicode]
Les contrôleurs étendent la classe abstraite Symfony\Bundle\FrameworkBundle\Controller\AbstractController
. Cela leur permettait entre autres dans Symfony 2, de récupérer les services et paramètres ainsi :
dump($this->get('session'));
dump($this->getParameter('kernel.project_dir'));
Depuis Symfony 4, il faut injecter le service service_container pour accéder à la liste des services publiques (public: true
en YAML), mais la bonne pratique est d'injecter uniquement les services nécessaires dans le constructeur[8][9].
Les paramètres sont ceux des fichiers .yml du dossier "config", mais plusieurs autres paramètres sont fournis par Symfony :
bin/console debug:container --parameters
- kernel.debug : renvoie vrai si le site est en préprod et faux en prod.
- kernel.project_dir : dossier racine (qui contient bin/, config/, src/, var/, vendor/).
- kernel.build_dir.
- kernel.cache_dir.
- kernel.logs_dir.
- kernel.root_dir : deprecated en SF5.3. Chemin du site dans le système de fichier.
- kernel.bundles : liste JSON des bundles chargés.
Routing[modifier | modifier le wikicode]
Par exemple pour créer une nouvelle page sur l'URL :
http://localhost:8000/test
Installer le routage :
composer require sensio/framework-extra-bundle composer require symfony/routing
Par défaut, la page renvoie l'exception No route found for "GET /test". Pour la créer, il faut d'abord générer un fichier contrôleur (rôle MVC), qui fera le lien entre les URL, les données (modèle) et les pages (vue).
Les URL définies dans l"annotation "@Route" d'une méthode exécuteront cette dernière :
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class TestController extends AbstractController
{
#[route('/test/{numero}', name: 'test', requirements: ['id' => '\d*'], methods: ['GET', 'POST'], priority: -1)]
public function HelloWorldAction(int $numero = 0)
{
return new Response('Hello World! '.$numero);
}
}
NB : en PHP < 8, remplacer l'attribut par une annotation :
/** * @Route("/test/{numero}", name="test", requirements={"id"="\d*"}, methods={"GET|POST"}, priority=-1) */
Autres exemples de prérequis :
requirements={"id"="fr|en"}
requirements={"id"="MaClasse::MA_CONSTANTE1|MaClasse::MA_CONSTANTE2"}
requirements={"id"="(?!api/doc|_profiler).*"}
Alias[modifier | modifier le wikicode]
Pour créer des alias, c'est-à-dire plusieurs autres URL pointant vers la page ci-dessus, on peut l'ajouter dans les annotations des contrôleurs, ou bien dans config/routes.yaml (anciennement app\config\routing.yml sur Symfony < 4) :
test:
path: /test/{numero}
defaults: { _controller: AppBundle:Test:HelloWorld }
À présent http://localhost:8000/test/1 ou http://localhost:8000/test/2 affichent "Hello World!".
- Une fois le YAML sauvegardé, l'URL fournie en annotation (/test) ne fonctionne plus.
- S'il y a des annotations précédant @Route dans le même bloc, cela peut inhiber son fonctionnement.
Redirection vers la dernière page visitée[modifier | modifier le wikicode]
Une astuce pour rediriger l'utilisateur vers la dernière page qu'il avait visité :
$router = $this->get('router');
$lastPage = $request->getSession()->get('last_view_page');
$parameterLastPage = $router->match($lastPage);
$routeLastPage = $parameterLastPage['_route'];
unset($parameterLastPage['_route']); // Pour ne pas la voir dans l'URL finale
return $this->redirect(
$this->generateUrl($routeLastPage, $parameterLastPage)
);
Annotations.yaml[modifier | modifier le wikicode]
Ce fichier permet de définir des groupes de contrôleurs, dont les routes sont préfixées. Ex :
back_controllers:
resource: ../../src/Controller/BackOffice
type: annotation
prefix: admin
front_controllers:
resource: ../../src/Controller/FrontOffice
type: annotation
prefix: api
Dans le cas où les contrôleurs ont des contrôles d'accès différents dans security.yaml, il est impératif de les préfixer ainsi pour éviter toute collision des gardiens.
Paramètres spéciaux[modifier | modifier le wikicode]
Il existe quatre paramètres spéciaux que l'on peut placer dans routes.yaml ou en argument des méthodes des contrôleurs[11] :
- _controller : contrôleur appelé par le chemin.
- _ format : format de requête (ex : html, xml).
- _fragment : partie de l'URL après "#".
- _locale : langue de la requête (code ISO, ex : fr, en).
Exemple :
#[Route('/controller_route', requirements: ['_locale' => 'en|fr'])] class MyController extends AbstractController
Vue[modifier | modifier le wikicode]
Pour commencer à créer des pages plus complexes, il suffit de remplacer :
return new Response('Hello World!');
par une vue issue d'un moteur de template. Celui de Symfony est Twig :
return $this->render('helloWorld.html.twig');
Pour installer les bibliothèques JavaScript qui agiront sur ces pages, se positionner dans /public. Exemple :
cd public/
sudo apt-get install npm
npm install --save jquery
npm install --save bootstrap
Ensuite il suffit de les appeler dans /templates/helloWorld.html.twig pour pouvoir les utiliser :
<link rel="stylesheet" href="{{ asset('node_modules/bootstrap/dist/css/bootstrap.min.css') }}">
<script type="text/javascript" src="{{ asset('node_modules/jquery/dist/jquery.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('node_modules/bootstrap/dist/js/bootstrap.min.js') }}"></script>
Modèle[modifier | modifier le wikicode]
Pour gérer le modèle du MVC, c'est-à-dire la structure des données stockées, l'ORM officiel de Symfony se nomme Doctrine.
Par défaut, ses classes sont :
- src/Entity : les entités, reflets des tables.
- src/Repository : les requêtes SELECT SQL (ou find MongoDB).
Références[modifier | modifier le wikicode]
- ↑ http://guidella.free.fr/General/symfony2AnnotationsReference.html
- ↑ http://mikinfo.free.fr/index.php/configurer-les-virtualhosts-pour-symfony/
- ↑ https://symfony.com/doc/current/setup/web_server_configuration.html
- ↑ https://symfony.com/doc/current/console/input.html
- ↑ https://symfony.com/doc/current/console/input.html
- ↑ https://symfony.com/doc/current/controller.html
- ↑ https://stackoverflow.com/questions/14449967/symfony-setting-flash-and-checking-in-twig
- ↑ https://symfony.com/doc/current/best_practices.html#use-dependency-injection-to-get-services
- ↑ https://symfony.com/doc/4.0/best_practices/controllers.html#fetching-services
- ↑ https://symfony.com/doc/current/security/voters.html
- ↑ https://symfony.com/doc/current/routing.html#special-routing-parameters
- « Wiki officiel »
- « Tutoriel openclassrooms.com »
- « Tutoriel developpez.com »
- (en) « Symfony 3.1 cookbook » : livre officiel de 500 pages
- (en) « Charming Development in Symfony 5 » (texte et vidéo)
Voir aussi[modifier | modifier le wikicode]
- #symfony : canal IRC (#symfony sur Freenode)
- #symfony-fr : canal IRC francophone (#symfony-fr sur Freenode)
- https://sonata-project.org/get-started : un CMS basé sur Symfony