- <h1>Hello !</h1>
- <p>What king of music do you like ?</p>
- <p>Maybe {{ category }} ?</p>
Symfony est un ensemble de composants PHP ainsi qu'un framework MVC libre écrit en PHP. Il fournit des fonctionnalités modulables et adaptables qui permettent de faciliter et d’accélérer le développement d'un site web.
L'initiateur du projet Symfony est le français Fabien Potencier.
Source : Wikipedia.fr
Afin d'utiliser Symfony, on peut opter pour deux solutions :
Pour l'installation de la machine virtuelle, voici la procédure à suivre.
Le framework Symfony utilise les espaces de nom (namespace) en PHP afin de gérer les différentes classes qu'il utilise.
Les espaces de nom en PHP sont en quelque sorte des dossiers virtuels qui servent à encapsuler certains objets afin de les différentier d'autres objets de même nom.
Symfony utilise deux types d'éléments (classes) :
Voici quelques exemples de components (composants) que l'on peut installer en utilisant composer (Composer is a tool for dependency management in PHP) :
Le framework Laravel utilise notamment ces trois classes.
En ce qui concerne les bundles, on trouve par exemple :
richer@zentopia:~\$ symfony new mon_projet
* Creating a new Symfony project with Composer
WARNING: Unable to find Composer, downloading one. It is recommended to install Composer yourself at https://getcomposer.org/download/
(running /home/richer/.symfony5/composer/composer.phar create-project symfony/skeleton /home/richer/dev/symfony/mon_projet --no-interaction)
* Setting up the project under Git version control
(running git init /home/richer/dev/symfony/mon_projet)
[OK] Your project is now ready in /home/richer/dev/symfony/mon_projet
Note : on peut également ajouter --webapp à la commande précédente pour indiquer qu'il s'agit d'un site web.
Un simple projet contient plus de 270 répertoires et plus de 1500 fichiers. Voici l'organisation du projet dans le répertoire qui a été créé :
richer@zentopia:~/dev/symfony/mon_projet\$ tree -L 1
.
├── bin
├── composer.json
├── composer.lock
├── config
├── public
├── src
├── symfony.lock
├── var
└── vendor
L'utilisation de la console peut être réalisé par :
php bin/console
# ou
symfony console
On peut utiliser VSCode pour gérer le projet, en lançant par exemple la commande :
richer@zentopia:~/\$ code ./mon_projet
Comme mentionné précédemment, toutes les requêtes au site web passent par le fichier index.php. Ce script réalise les actions suivantes :
Lors de l'envoi d'une requête au serveur web, ce dernier la transmet à php-fpm (FastCGI Process Manager) qui exécute le script
Ce fichier est appelé point d'entrée ou
On crée une instance de la classe
Cette classe appelle notamment une fonction
On détermine également dans cette fonction quel contrôleur appeler en fonction des routes existantes (redirections).
La Response contient des headers, du contenu et un code d'erreur.
Le mode de fonctionnement des frameworks pour le web s'appuie sur une modèle Route / Controller :
Un contrôleur sera placé dans le répertoire
Le contrôleur est une classe de même nom que le fichier auquel elle appartient.
Il dispose d'une ou plusieurs fonctions qui vont traiter une requête et vont retourner une réponse.
Voici un contrôleur basique qui retourne du code HTML :
Dans l'exemple précédent, on a créé, par l'intermédiaire d'une annotation, l'assocation entre le contrôleur et la route. Le contrôleur doit retourner une réponse (Response).
Imaginons que l'on désire passer un paramètre sur le type de musique que l'on désire consulter. Il est possible de passer en paramètre de la fonction un paramètre comme suit. On va définir dans la même classe, une autre méthode qui permet de traiter une autre route :
Si la paramètre
On pourrait construire chaque page dans le contrôleur mais cela serait fastidieux. Il est en général préférable d'utiliser des templates qui sont introduits par Twig.
Twig est un moteur de templates pour le langage de programmation PHP, utilisé par défaut par le framework Symfony.
Pour cela on crée par exemple, dans le répertoire
Au niveau de notre contrôleur, on ajoute une route
Le fichier de templates a le format suivant :
On peut passer un autre paramètre au renderer, dans le cas présent, on va lui passer un tableau.
On utilise alors la structure de contrôle
Les filtres permettent de modifier l'affichage des variables ou la transformation des variables qui sont introduits par le symbole '|'.
Par exemple,
{{ 'mon titre' | upper }}
Un autre filtre intéressant est
// introduisez une variable 'code' au niveau du contrôleur qui contient du code HTML
// puis affichez la avec l'une des deux syntaxes suivantes :
{{ code }}
{{ code | raw }}
Le filtre
{{ [ 2, 3, 5, 7 ] | join( ',' ) }}
Le filtre
{{ [ 2, 3, 5, 7 ] | map( x => x * x ) | join( ',' ) }}
On obtiendra donc la chaîne "4, 9, 25, 49".
Le filtre
{% for x in [1,2,3,4,5,6] | filter( x => (x % 2) == 0 ) %}
{{ x }}
{% endfor %}
On obtient donc uniquement les nombres pairs.
A partir d'un timestamp, on peut obtenir la date et l'afficher au format jour / mois /année :
{{ 23580000 | date('d/m/Y') }}
On peut également choisir d'afficher la date au format jour / mois en lettres / année mais dans ce cas on obtient un mois en anglais.
{{ 23580000 | date('d F Y') }}
Il faut alors utiliser le filtre
symfony composer require twig/intl-extra
symfony composer require twig/extra-bundle
Il existe également
{{ 23580000 | format_date( pattern="dd MMMM yyyy", locale='fr' ) }}
Néanmoins, il faut aujouter le package Linux correspondant (par exemple
...
;extension=gettext
;extension=gmp
extension=intl
;extension=imap
;extension=mbstring
...
Il est possible de créer un template Twig et de l'inclure dans un autre template, en passant des paramètres :
{{ include( "template_a_inclure.twig",
{ var : nom_var } ) }}
Le code de base d'une page est donné par le fichier
Cette page contient des
Cette variable permet d'avoir accès à différentes informations comme l'utilisateur connecté, les paramètres passés, environnement (développement, production), les variables de session.
On peut notamment afficher la requête en tapant :
{{ dump( app.request ) }}
{{ dump( app.request.method ) }}
{{ dump( app.request.environment ) }}
{{ dump( app.request.session ) }}
Il faut vérifier que le bundle form est bien installé, sinon il faudra l'installer :
symfony composer require form
Pour gérer un formulaire, il faut :
Commencez par créer un nouveau controller en utilisant la console :
symfony console make:controller
PHP Warning: Module "intl" is already loaded in Unknown on line 0
Choose a name for your controller class (e.g. OrangePizzaController):
> FormController
created: src/Controller/FormController.php
created: templates/form/index.html.twig
Success!
On peut créer un formulaire spécifique en chaînant les différents type de champs entre eux et en définissant leurs caractéristiques. Ici, on va créer un formulaire avec un prénom (first name) à saisir ainsi qu'un bouton pour soumettre les données saisies :
Voir la page des Types de champs définis par Symfony.
Il faut commencer par appeler la fonction
Un champ est défini par un nom (string), un type (XXX::class) et éventuellement une liste d'attributs [].
On termine en appelant la fonction
Puis, il faut afficher le formulaire dans une page, en passant en paramère \$myForm->createView().
On utilise \$myForm->handleRequest(\$request); pour traiter les données et remplir le formulaire
Si on veut envoyer les données vers la base de données, il faudra vérifier que les données ont été soumises et sont valides :
Soit une classe personne composée de deux champs : first_name et genre (sexe) :
Pour gérer cette structure, il faut en créer une instance et faire en sorte que les champs à saisir aient le même nom que les champs de la classe.
Si on désire saisir un champ mais qu'il ne fasse pas partie de la classe il faut utiliser l'attribut
On peut manipuler une liste de Pays, des Date / DateTime, des checkbox, des radio button, etc. Voici un petit exemple :
Exercice 1.1
Créer un formulaire qui permet de saisir les informations suivantes :
On peut suivre la documentation Doctrine de Symfony pour cette partie ou suivre ce qui suit.
Pour installer MySQL 8.0, on peut suivre le tutoriel : MySQL how to install on Ubuntu. Personnellement, j'ai suivi la procédure suivante car Symfony refusait de créer une base de données en utilisant le compte root.
En utilisant le compte root, on peut créer une base de données ccp (Client Command Product) et un utilisateur qui pourra agir sur cette base de données :
mysql> create database ccp;
mysql> create user 'ccp_user'@'localhost' identified by 'ccp_user_pwd';
mysql> grant all privileges on ccp.* to 'ccp_user'@'localhost';
mysql> flush privileges;
Pour rappel l'ORM ou Object Relational Mapping consiste à transformer les tables du modèle relationnel à des classes dans un langage object (tels PHP, Java ou C++).
On peut réaliser cela avec PDO met on ne chargera que les enregistrements d'une table client par exemple. L'ORM permet de charger les clients et à partir d'un client, d'obtenir une ou des commandes, et à partir d'une commande, d'obtenir les produits commandés.
Doctrine définit deux classes :
Pour installer Doctrine, si celui-ci n'est pas installé, il suffit de saisir dans la console :
symfony composer require orm
Il faut commencer par configurer l'accès à la base de données en modifiant le fichier
...
DATABASE_URL="mysql://root:tiger@127.0.0.1:3306/ccp?serverVersion=8&charset=utf8mb4"
...
Ici, on utilise MySQL sur le port 3306. Il s'agit d'une installation Docker pour laquelle le mot de passe du root est tiger. Le nom de la base de données est ccp.
On lance ensuite la création de la base :
symfony console doctrine:database:create
Pour créer une nouvelle entité (class / table), on utilise la commande suivante :
symfony console make:entity
Class name of the entity to create or update (e.g. OrangePuppy):
> Client
created: src/Entity/Client.php
created: src/Repository/ClientRepository.php
Entity generated! Now let's add some fields!
You can always add more fields later manually or by re-running this command.
New property name (press to stop adding fields):
> name
Field type (enter ? to see all types) [string]:
>
Field length [255]:
> 30
Can this field be null in the database (nullable) (yes/no) [no]:
> no
updated: src/Entity/Client.php
Add another property? Enter the property name (or press to stop adding fields):
>
Success!
Next: When you're ready, create a migration with php bin/console make:migration
On a ainsi créé :
On peut modifier name, length, precision, nullable, ...
Il faut ensuite réaliser une migration, c'est à dire répercuter les modifications au niveau du serveur de la base de données :
symfony console make:migration
On peut ensuite vérifier que la modification a été effectuée :
richer@zentopia\$ mysql -h 127.0.0.1 -P 3306 -u root -p
mysql> use ccp
Database changed
mysql> show tables;
+-----------------------------+
| Tables_in_ccp |
+-----------------------------+
| client |
| doctrine_migration_versions |
| messenger_messages |
+-----------------------------+
3 rows in set (0,00 sec)
mysql> describe client;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0,01 sec)
On demande la création d'un formulaire pour un client :
richer@zentopia\$ symfony console make:form
The name of the form class (e.g. OrangePopsicleType):
> ClientForm
The name of Entity or fully qualified model class name that the new form will be bound to (empty for none):
> Client
created: src/Form/ClientType.php
Success!
Next: Add fields to your form and start using it.
Find the documentation at https://symfony.com/doc/current/forms.html
Symfony crée un fichier
On crée également un contrôleur pour gérer cette forme :
richer@zentopia\$ symfony console make:controller
Choose a name for your controller class (e.g. GrumpyElephantController):
> ClientFormController
created: src/Controller/ClientFormController.php
created: templates/client_form/index.html.twig
Success!
Next: Open your new controller class and add some pages!
Le code du contrôleur est donc le suivant :
A partir d'un
Pour obtenir des données depuis la base de données il faut utiliser un Repository, celui-ci a été créé lors de la création d'une entité.
A partir de la route
Le rendu par Twig peut être le suivant :
Il existe bien d'autres fonctions comme :
Par exemple, on peut écrire les critères suivants pour obtenir tous les produits qui sont des claviers et les trier suivant leur prix en ordre croissant :
\$products = \$repository->findBy(
['name' => 'Keyboard'],
['price' => 'ASC']
);
Voir la documentation de Doctrine : Updating an object.
Voir la documentation de Doctrine : Deleting an object.
Exercice 1.2
Mettre en place des routes pour ajouter / modifier / supprimer / donner la liste de clients dont les champs sont :
Il est possible de créer des relations entre les entités qui correspondent aux relations entre entités dans la base de données. Il suffit de définir un champ avec un type relation et de qualifier cette relation sous une des formes : OneToOne, OneToMany, ManyTiOne, ManyToMany.