• Créer la route :
ajouter à config/routes.yaml :
salle_tp_accueil:
path: /accueil
controller: App\Controller\SalleController::accueil
◦ c’est du Yaml :
• l'indentation se fait avec des espaces (mais le même nombre d’espace
exactement !) et surtout pas avec des tabulations !!
◦ Le nom de la route est salle_tp_accueil
▪ son path spécifie que l'URL aura pour chemin /accueil
▪ le contrôleur qui traitera sera : SalleController
▪ et la méthode/fonction à exécuter sera accueil
class SalleController {
public function accueil() {
return new Response("ici l'accueil !");
}
}
◦ Tester http://localhost:8000/accueil
◦ puis changer la réponse :
return new Response("<html><body><h1>Salles :</h1> <p>Voici quelques
informations concernant les salles<br \>blablabla blablabla blablabla blablabla
blablabla blablabla blablabla blablabla ....</p></body></html>");
▪ et re-tester http://localhost:8000/accueil
• Ajout de packages/bundles :
◦ la version 4 de Symfony est "minimaliste" : elle installe le minimum de composants.
Le développeur peut ajouter des packages/bundles supplémentaires. Cela se fait à
l'aide de "recipes" (recettes) utilisant Flex, donc composer.
▪ Les "recipes" peuvent être "official" ou "contrib" cad proposée par la communauté
▪ Ajoutons symfony/debug https://packagist.org/packages/symfony/debug
composer require --dev debug
• par dépendance, il ajoute aussi le composant symfony/twig-bundle : le moteur
de template TWIG
▪ et re-tester http://localhost:8000/accueil
• Créer un template
◦ Twig est un moteur de template qui simplifie le travail d'affichage de la vue :
il évite les fastidieux appels PHP : <?php echo $a; ?>
◦ créer le fichier templates/salle/accueil.html.twig
<!DOCTYPE html>
<html>
<head>
<title>Accueil</title>
</head>
<body>
<h1>Salles :</h1>
<p> Voici quelques informations concernant les salles<br \>
En particulier, la salle {{ numero }} <br \>
blablabla blablabla blablabla blablabla blablabla blablabla blablabla
blablabla ....
</p>
</body>
</html>
• Le contrôleur fait appel au moteur de rendu de template
et a besoin pour cela d’hériter d’AbstractController
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
• Ajoutons une action « afficher une salle » avec en paramètre son numéro :
◦ éditer SalleController.php :
▪ créer l’action afficher et ajouter un paramètre à l'action
public function afficher($numero) {
return $this->render('salle/afficher.html.twig',
array( 'numero' => $numero ));
}
◦ ajouter une route à config/routes.yaml :
salle_tp_afficher:
path: /afficher/{numero}
controller: App\Controller\SalleController::afficher
◦ ajouter un template
▪ créer le fichier templates/salle/afficher.html.twig
<!DOCTYPE html>
<html>
<head>
<title>Salle</title>
</head>
<body>
<h1>Salle {{ numero }}</h1>
<p> Voici quelques informations concernant la salle numéro : {{ numero }}<br \>
blablabla {{ numero }} blablabla {{ numero }} blablabla {{ numero }}
blablabla {{ numero }} blablabla {{ numero }} ....
</p>
</body>
</html>
◦ Tester http://localhost:8000/afficher/999
Salle 999
Voici quelques informations concernant la salle de numéro : 999
blablabla 999 blablabla 999 blablabla 999 blablabla 999 blablabla 999 ....
• Ajoutons une image dans le répertoire public/images
et, dans le template, le code suivant ;
<body>
<img src="/images/logo-UPJV.png" />
<h1>Salle {{ numero }}</h1>
◦ Tester http://localhost:8000/afficher/999
Exercices 1.1
• Avant de changer de projet, arrêter le serveur
$ symfony server:stop
• Créer un projet guideMichelin
• Puis créer une page d'accueil affichant « Bonjour : Guide Michelin .. trouvez un
restaurant » de routing /accueil
Architecture du framework
Il fonctionne selon l'architecture MVC modèle vue contrôleur.
Structure simplifiée d’un projet symfony :
config/
les fichiers de configuration générale
routes.yaml les routes
...
bin/
les exécutables
console.php utilitaire de développement
src/
votre code Php !
Les contrôleurs, au sens MVC, analysent et traitent la requête, utilisent si nécessaire le modèle,
préparent la réponse : SalleControlleur.php, ….
Chaque contrôleur possède une ou plusieurs méthodes/fonctions
templates/
les templates, les vues , au sens MVC, affichent la réponse
var/
les fichiers créés :
cache/
Pour un traitement accéléré, Symfony met beaucoup de fichiers en cache : cela pose
quelques fois des Pbs !
log/ les logs de, notamment, vos erreurs
vendor/
répertoire des librairies chargées par composer
symfony/
doctrine/
twig/
...
public/
répertoire racine du projet
index.php qui appelle le app/AppKernel.php avec la requête en cours
les fichiers public (images, CSS, javascript…)
La gestion du cache :
si Pb de modification non prise en compte
Symfony est rapide grâce à sa mise en cache des pages déjà calculées. Mais, quelques fois,
un changement peut ne pas être pris en compte :
• En mode dev, normalement à chaque changement, Symfony recalcule une bonne partie
du cache. Si des dépendances ne sont pas prises en compte, tapez la commande :
symfony console cache:clear
• Si elle "crache" des erreurs, ou si ça ne suffit pas, supprimez le contenu de
app/cache
Routing
• Module de Symfony basée sur un ensemble de règles qui associent une URL à une
action (≈ l’URL Rewriting).
• Définition du routing :
◦ (++) Symfony propose 4 techniques de définition des règles : les annotations, le
YAML, XML et PHP
Attention : ne pas mélanger les techniques !
▪ Par fichier de configuration YAML du bundle :
donc config/routes.yaml
// déjà programmée !
salle_tp_afficher:
path: /afficher/{numero}
controller: App\Controller\SalleController::afficher
▪ Par annotation dans les contrôleurs :
• Pour cela, lancer la "recipe" :
// ne pas executer !
composer require annotations
// ne pas programmer
class SalleController extends Controller {
...
/**
* @Route("/afficher/{numero}", name="salle_tp_afficher")
*/
public function afficher($numero) {
return $this->render('salle/afficher.html.twig', array(
'numero' => $numero ));
}
}
▪ Par fichier de configuration XML routing.xml :
// ne pas programmer !
<?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="salle_tp_accueil" path="/accueil" controller="App\Controller\
SalleController::accueil" />
<route id="salle_tp_afficher" path="/afficher/{numero}" controller="App\Controller\
SalleController::afficher" />
</routes>
salle_tp_afficher:
path: /afficher/{numero}
controller: App\Controller\SalleController::afficher
requirements:
numero: \d{1,2}
▪ Changer config/routes.yaml ainsi :
salle_tp :
resource: routes/salle/routes.yaml
prefix: /salle
Utiliser des préfixes distincts pour chaque contrôleur ou bundle afin d’éviter les
conflits de résolution de route !
▪ Essayer http://localhost:8000/salle/afficher/24 : çà marche !
◦ dans un template :
Modifier le fichier twig templates/salle/afficher.html.twig:
la fonction path construit l'url à partir d'un nom de route
...
<p>lien vers <a href="{{ path('salle_tp_afficher', { 'numero': numero +
1 }) }}">
la suivante</a></p>
<p>lien vers <a href="{{ path('salle_tp_accueil') }}">l'accueil</a></p>
</body>
</html>
▪ Le résultat donne :
…
lien vers la suivante
lien vers l'accueil
• Générer une erreur/exception :
◦ Par conséquent, une réponse HTTP 404 : ce n'est pas une route mais une
fonctionnalité du contrôleur !
◦ Modifier la méthode afficher du contrôleur SalleController.php :
public function afficher($numero) {
if ($numero > 50)
throw $this->createNotFoundException('C\'est trop !');
else
return $this->render('salle/afficher.html.twig',
array('numero' => $numero));
}
▪ Essayer http://localhost:8000/salle/afficher/51 :
◦ (++) Il est préférable que l’utilisateur soit informé et renvoyé vers l’accueil de
l’application : une solution simple est de surcharger les templates d’erreur et
d’exception
Exercices 1.2
• modifier la configuration générale du routing pour que toutes les routes commencent
par /guideMichelin. En particulier, la page d’accueil sera dorénavant accessible via
guideMichelin/accueil.
• Ajouter un lien dans la page d’accueil vers une page menu qui comportera la phrase
« Bienvenue dans le menu du Guide Michelin » de routing /guideMichelin/menu. La page
menu comportera un lien pour revenir à la page d’accueil.
• Apporter les modifications nécessaires pour que sur la page d’accueil s’affiche le nom
donné en paramètre de la route correspondant à l’accueil. Exemple :
/guideMichelin/accueil/Didier affichera la page d’accueil avec la mention « Bonjour
Didier : Guide Michelin ...trouvez un restaurant ». Si le paramètre nom n’est pas
renseigné, la page d’accueil devra simplement avoir le même affichage qu’avant.
Entité
• installation de la librairie Doctrine pour Symfony afin d’accéder simplement aux bases de
données et des outils de création de contrôleurs, entités, ..
composer require symfony/orm-pack
composer require --dev symfony/maker-bundle
◦ Générons, interactivement en console, une entité qui représente une salle avec 3
champs : bâtiment de type string, étage et numéro de type entier.
L'entité se nommera … Salle dans notre bundle.
Add another property? Enter the property name (or press <return> to stop adding fields):
> etage
Field type (enter ? to see all types) [string]:
> smallint
Can this field be null in the database (nullable) (yes/no) [no]:
>
Add another property? Enter the property name (or press <return> to stop adding fields):
> numero
Field type (enter ? to see all types) [string]:
> smallint
Can this field be null in the database (nullable) (yes/no) [no]:
>
Add another property? Enter the property name (or press <return> to stop adding fields):
>
Success!
class Salle {
private $id;
private $batiment;
private $etage;
private $numero;
return $this;
}
...
}
salle_tp_quatorze:
path: /quatorze
controller: App\Controller\SalleController::quatorze
▪ Essayer http://localhost:8000/salle/treize :
• batiment D
• etage 1
• numero 13
/**
* @ORM\Entity(repositoryClass="App\Repository\SalleRepository")
*/
class Salle
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=1)
*/
private $batiment;
/**
* @ORM\Column(type="smallint")
*/
private $etage;
/**
* @ORM\Column(type="smallint")
*/
private $numero;
...
}
▪ L'annotation Table permet de définir un nom pour la table qui sera créée en base
de donnée : cette annotation est facultative.
▪ L'annotation Entity permet d'indiquer que l'objet est une entité (qui devra donc être
éventuellement persistée en BD).
▪ L'annotation Column s'applique sur un attribut de la classe : elle permet d'indiquer
les propriétés que devra avoir la colonne de la table correspondant à l'attribut.
• Preparez la migration de la base de données :
symfony console make:migration
Le fichier généré contient la bonne séquence SQL de création de la table Salle dans la
base de données.
◦ Mettez à jour la base de données :
symfony console doctrine:migrations:migrate
WARNING! You are about to execute a database migration that could result in schema
changes and data loss. Are you sure you wish to continue? (y/n)y
Migrating up to 20190705165125 from 0
-> CREATE TABLE salle (id INT AUTO_INCREMENT NOT NULL, batiment VARCHAR(1) NOT
NULL, etage SMALLINT NOT NULL, numero SMALLINT NOT NULL, PRIMARY KEY(id)) DEFAULT
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB
◦ Avec Phpmyadmin, vérifiez la nouvelle structure de la base.
Puis ajoutez quelques salles dans la table ….
INSERT INTO `salle` (`batiment`, `etage`, `numero`) VALUES
('B', 1, 23), ('B', 1, 22), ('D', 1, 12);