Computers">
Apprenez Symfony 3
Apprenez Symfony 3
Apprenez Symfony 3
#symfony3
Table des matières
À propos 1
Remarques 2
Versions 2
Examples 2
3. Systèmes Windows 2
Introduction 7
Paramètres 7
Remarques 7
Examples 7
Chapitre 3: Configuration 8
Introduction 8
Examples 8
Examples 11
Chapitre 5: Essai 15
Examples 15
Examples 18
Comment étendre ChoiceType, EntityType et DocumentType pour charger des choix avec AJAX. 18
Chapitre 7: Le routage 22
Introduction 22
Remarques 22
Examples 22
Syntaxe 26
Remarques 26
Examples 26
Examples 28
Remarques 33
Examples 33
Crédits 43
À propos
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: symfony3
It is an unofficial and free symfony3 ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official symfony3.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@zzzprojects.com
https://riptutorial.com/fr/home 1
Chapitre 1: Démarrer avec symfony3
Remarques
Cette section fournit une vue d'ensemble de ce qu'est symfony3 et pourquoi un développeur peut
vouloir l'utiliser.
Il devrait également mentionner tous les grands sujets dans symfony3, et établir un lien avec les
sujets connexes. La documentation de symfony3 étant nouvelle, vous devrez peut-être créer des
versions initiales de ces rubriques connexes.
Versions
3.0.0 2015-11-30
3.1.0 2016-05-30
3.2.0 2016-11-30
3.2.5 2017-03-09
3.2.6 2017-03-10
3.2.7. 2017-04-05
Examples
3. Systèmes Windows
Vous devez ajouter php à votre variable d'environnement de chemin. Suivez ces étapes:
Windows 7 :
https://riptutorial.com/fr/home 2
• Fermez votre invite de commande et ouvrez-le à nouveau
• Trié
Windows 8 et 10
Ensuite, déplacez le fichier symfony téléchargé dans le répertoire de votre projet et exécutez-le
comme suit:
Une fois le programme d'installation de Symfony disponible, créez votre première application
Symfony avec la nouvelle commande:
# Linux, Mac OS X
$ symfony new my_project_name
# Windows
c:\> cd projects/
c:\projects\> php symfony new my_project_name
Cette commande peut être exécutée depuis n’importe où, pas nécessairement depuis le dossier
htdocs .
Cette commande crée un nouveau répertoire appelé my_project_name/ qui contient un nouveau
projet basé sur la version stable la plus récente de Symfony disponible. De plus, le programme
d'installation vérifie si votre système répond aux exigences techniques pour exécuter des
applications Symfony. Sinon, vous verrez la liste des modifications nécessaires pour répondre à
ces exigences.
https://riptutorial.com/fr/home 3
de Symfony. Lisez la section Création d'applications Symfony sans le programme
d'installation pour savoir comment procéder. - source:
http://symfony.com/doc/current/book/installation.html
Si votre projet doit être basé sur une version spécifique de Symfony, utilisez le second argument
facultatif de la nouvelle commande:
Le programme d'installation prend également en charge une version spéciale appelée lts qui
installe la version la plus récente de Symfony LTS disponible:
Lisez le processus de publication de Symfony pour mieux comprendre pourquoi il existe plusieurs
versions de Symfony et lesquelles utiliser pour vos projets.
Vous pouvez également créer des applications symfony sans le programme d'installation, mais ce
n'était pas une bonne idée. Si vous voulez quand même, suivez le tutoriel original sur ce lien:
https://riptutorial.com/fr/home 4
6. Testez l'exemple en visitant http: // localhost: 8000 / hello
7. C'est tout. Suivant: utilisez twig pour rendre la réponse.
<?php
// src/AppBundle/Controller/MyController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
class MyController
{
/**
* @Route("/hello")
*/
public function myHelloAction()
{
return new Response(
'<html><body>
I\'m the response for request <b>/hello</b>
</body></html>'
);
}
}
Supposons que vous vouliez créer une page - / lucky / number - qui génère un numéro de chance
(bien, aléatoire) et l’imprime. Pour ce faire, créez une classe "Controller" et une méthode
"controller" à l'intérieur de celle-ci qui seront exécutées lorsque quelqu'un accédera à / lucky /
number
// src/AppBundle/Controller/LuckyController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
class LuckyController
{
/**
* @Route("/lucky/number")
*/
public function numberAction()
{
$number = rand(0, 100);
https://riptutorial.com/fr/home 5
Lire Démarrer avec symfony3 en ligne: https://riptutorial.com/fr/symfony3/topic/985/demarrer-
avec-symfony3
https://riptutorial.com/fr/home 6
Chapitre 2: Asset Management avec Assetic
Introduction
Lorsque vous utilisez le bundle Assetic, conformément à la documentation Symfony, veuillez
prendre en compte les éléments suivants:
À partir de Symfony 2.8, Assetic n'est plus inclus par défaut dans Symfony Standard Edition.
Avant d'utiliser l'une de ses fonctionnalités, installez AsseticBundle en exécutant cette commande
de console dans votre projet:
Paramètres
prénom Exemple
Remarques
Le dossier des actifs accessibles au public dans un projet Symfony3 standard est "/ web". Assetic
utilise ce dossier en tant que dossier racine pour les actifs.
Examples
Créer un chemin relatif pour l'actif
https://riptutorial.com/fr/home 7
Chapitre 3: Configuration
Introduction
Exemples et bonnes pratiques pour configurer votre application Symfony qui ne figurent pas dans
la documentation officielle.
Examples
Inclure tous les fichiers de configuration d'un répertoire
Après un certain temps, vous obtenez de nombreux éléments de configuration dans votre
config.yml. Il peut vous rendre la configuration plus facile à lire si vous divisez votre configuration
sur plusieurs fichiers. Vous pouvez facilement inclure tous les fichiers d'un répertoire de cette
manière:
config.yml:
imports:
- { resource: parameters.yml }
- { resource: "includes/" }
Dans le includes répertoire que vous pouvez mettre par exemple doctrine.yml, swiftmailer.yml, etc.
services:
acme.demo.service.id:
class: Acme\DemoBundle\Services\DemoService
arguments: ["@doctrine.orm.default_entity_manager", "@cache"]
$service = $this->get('acme.demo.service.id');
Bien qu'il n'y ait pas de problème avec cela, vous pouvez utiliser un nom de classe pleinement
qualifié (FQCN) comme identifiant de service:
services:
Acme\DemoBundle\Services\DemoService:
class: Acme\DemoBundle\Services\DemoService
arguments: ["@doctrine.orm.default_entity_manager", "@cache"]
https://riptutorial.com/fr/home 8
Dans votre contrôleur, vous pouvez l'utiliser comme ceci:
use Acme\DemoBundle\Services\DemoService;
// ..
$this->get(DemoService::class);
Cela rend votre code plus compréhensible. Dans de nombreux cas, cela n'a aucun sens d'avoir un
identifiant de service qui n'est pas seulement le nom de la classe.
A partir de Symfony 3.3, vous pouvez même supprimer l'attribut class si votre identifiant de service
est un FQCN.
Si votre application n'a besoin d'aucune interface HTTP (par exemple pour une application
uniquement console), vous souhaiterez désactiver au moins Twig et SensioFrameworkExtra
app / AppKernel.php
$bundles = [
//...
// new Symfony\Bundle\TwigBundle\TwigBundle(),
// new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
//...
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
//...
// $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
framework:
# ...
# router:
# resource: '%kernel.root_dir%/config/routing.yml'
# strict_requirements: ~
# ...
# templating:
# engines: ['twig']
#...
#twig:
# debug: '%kernel.debug%'
# strict_variables: '%kernel.debug%'
#framework:
# router:
# resource: '%kernel.root_dir%/config/routing_dev.yml'
# strict_requirements: true
# profiler: { only_exceptions: false }
https://riptutorial.com/fr/home 9
#web_profiler:
# toolbar: true
# intercept_redirects: false
"sensio/framework-extra-bundle": "x.x.x",
"twig/twig": "x.x"
L'utilisation de Symfony dans un tel cas est discutable, mais au moins cela peut être temporaire.
https://riptutorial.com/fr/home 10
Chapitre 4: Entités déclarantes
Examples
Déclaration d'une entité Symfony comme YAML
<?php
namespace AppBundle\Entity;
/**
* Person
*/
class Person
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var int
*/
private $age;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Person
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
https://riptutorial.com/fr/home 11
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set age
*
* @param integer $age
*
* @return Person
*/
public function setAge($age)
{
$this->age = $age;
return $this;
}
/**
* Get age
*
* @return int
*/
public function getAge()
{
return $this->age;
}
}
AppBundle\Entity\Person:
type: entity
repositoryClass: AppBundle\Repository\PersonRepository
table: persons
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 20
nullable: false
column: Name
unique: true
age:
type: integer
nullable: false
column: Age
unique: false
https://riptutorial.com/fr/home 12
lifecycleCallbacks: { }
• Créer la table
<?php
namespace AppBundle\Entity;
/**
* @ORM\Entity
* @ORM\Table(name="persons")
* @ORM\Entity(repositoryClass="AppBundle\Entity\PersonRepository")
* @UniqueEntity("name")
*/
class Person
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", name="name", length=20, nullable=false)
*/
protected $name;
/**
* @ORM\Column(type="integer", name="age", nullable=false)
*/
protected $age;
https://riptutorial.com/fr/home 13
}
• Générer l'entité
• Créer la table
https://riptutorial.com/fr/home 14
Chapitre 5: Essai
Examples
Tests simples dans Symfony3
Test de l'unité
Les tests unitaires permettent de s’assurer que votre code n’a pas d’erreur de syntaxe et de tester
la logique de votre code pour fonctionner comme prévu. Exemple rapide:
<?php
namespace AppBundle\Calculator;
use AppBundle\Calculator\TaxCalculator;
class BillCalculator
{
private $taxCalculator;
<?php
namespace AppBundle\Calculator;
class TaxCalculator
{
public function calculate($price)
{
return $price * 0.1; // for example the tax is 10%
}
}
https://riptutorial.com/fr/home 15
tests / AppBundle / Calculatrice / BillCalculatorTest.php
<?php
namespace Tests\AppBundle\Calculator;
$this->assertEquals(330, $price);
}
}
J'ai testé ma classe BillCalculator afin de m'assurer que mon BillCalculator retournera le prix total
des produits + 10% de taxe. Dans le test unitaire, nous créons notre propre cas de test. Dans ce
test, je fournis 2 produits (les prix sont 100 et 200), la taxe sera donc de 10% = 30. Je m'attends à
ce que TaxCalculator retourne 30, de sorte que le prix total sera de 300 + 30 = 330.
Test fonctionnel
Les tests fonctionnels sont utilisés pour tester les entrées et les sorties. Avec l'entrée donnée, je
m'attendais à une sortie sans tester le processus pour créer la sortie. (ceci est différent avec le
test unitaire car dans le test unitaire, nous testons le flux de code). Exemple rapide:
namespace Tests\AppBundle;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
https://riptutorial.com/fr/home 16
$client->request('GET', $url);
$this->assertTrue($client->getResponse()->isSuccessful());
}
J'ai testé mon contrôleur pour que mon contrôleur renvoie une réponse 200 au lieu de 400
(Introuvable) ou 500 (Erreur interne du serveur) avec l'URL indiquée.
Les références:
• http://symfony.com/doc/current/best_practices/tests.html
• http://symfony.com/doc/current/book/testing.html
https://riptutorial.com/fr/home 17
Chapitre 6: Formulaires dynamiques
Examples
Comment étendre ChoiceType, EntityType et DocumentType pour charger des
choix avec AJAX.
Si vous voulez le faire fonctionner avec les appels ajax, vous devez les modifier pour accepter les
choix supplémentaires cumulés.
Lorsque vous créez votre formulaire, définissez simplement l'option choices sur un array()
vide array() :
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
Vous obtiendrez donc une entrée de sélection vide, sans choix. Cette solution fonctionne
pour ChoiceType et tous ses enfants (EntityType, DocumentType, ...).
Pour accepter les nouveaux choix, vous devez les rendre disponibles dans la liste de
sélection des champs de formulaire. Vous pouvez modifier votre champ de formulaire en
fonction des données soumises avec l'événement FormEvent :: PRE_SUBMIT.
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
https://riptutorial.com/fr/home 18
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function(FormEvent $event){
// Get the parent form
$form = $event->getForm();
if(is_array($data)){
foreach($data as $choice){
$choices[$choice] = $choice;
}
}
else{
$choices[$data] = $data;
}
Vos choix soumis sont maintenant des choix autorisés et la validation intégrée de Symfony
ChoiceType ne les rejettera plus.
Cet exemple montre comment modifier les choix autorisés dans un champ de sélection de sous-
catégorie en fonction de la valeur du champ de sélection de catégorie. Pour ce faire, vous devez
rendre vos choix de sous-catégories dynamiques à la fois pour le client et pour le serveur.
https://riptutorial.com/fr/home 19
Exemple de formulaire dynamique côté client (en utilisant Javascript / JQuery):
$('#category').change(function(){
switch($(this).val()){
case '1': // If category == '1'
var choice = {
'choice1_1':'1_1',
'choice1_2':'1_2',
'choice1_3':'1_3',
};
break;
case '2': // If category == '2'
var choice = {
'choice2_1':'2_1',
'choice2_2':'2_2',
'choice2_3':'2_3',
};
break;
case '3': // If category == '3'
var choice = {
'choice3_1':'3_1',
'choice3_2':'3_2',
'choice3_3':'3_3',
};
break;
}
$subCategorySelect.empty();
$.each(choice, function(key, value) {
$subCategorySelect.append($('<option></option>')).attr('value',value).text(key);
});
});
Bien sûr, vous pouvez choisir parmi un appel AJAX. Ce n'est pas le but de cet exemple.
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
https://riptutorial.com/fr/home 20
$builder
->add('category',ChoiceType::class,array('choices'=>array(
'choice1'=>'1',
'choice2'=>'2',
'choice3'=>'3',
)))
;
switch($data['category']){
case '1': // If category == '1'
$choices = array(
'choice1_1'=>'1_1',
'choice1_2'=>'1_2',
'choice1_3'=>'1_3',
);
break;
case '2': // If category == '2'
$choices = array(
'choice2_1'=>'2_1',
'choice2_2'=>'2_2',
'choice2_3'=>'2_3',
);
break;
case '3': // If category == '3'
$choices = array(
'choice3_1'=>'3_1',
'choice3_2'=>'3_2',
'choice3_3'=>'3_3',
);
break;
}
$form->add('subCategory',ChoiceType::class,array('choices'=>$choices));
};
// This listener will adapt the form with the data passed to the form during
construction :
$builder->addEventListener(FormEvents::PRE_SET_DATA, $addSubCategoryListener);
// This listener will adapt the form with the submitted data :
$builder->addEventListener(FormEvents::PRE_SUBMIT, $addSubCategoryListener);
}
}
https://riptutorial.com/fr/home 21
Chapitre 7: Le routage
Introduction
Une route est comme mapper une URL à une action (fonction) dans une classe de contrôleur. La
rubrique suivante se concentrera sur la création d'itinéraires, en passant des paramètres à la
classe Controller via une route, à l'aide de YAML ou d'une annotation.
Remarques
Il est utile de voir ce qui est généré par le framework Symfony, celui-ci fournit des outils pour
regarder toutes les routes d'une application spécifique.
De plus, vous pouvez voir toutes les informations de routes pertinentes dans le profileur
Framework, dans le menu de routage:
Examples
Routage à l'aide de YAML
https://riptutorial.com/fr/home 22
La configuration du routage est incluse dans votre fichier app/config/config.yml , par défaut dans
le fichier app/config/routing.yml .
De là, vous pouvez créer un lien vers votre propre configuration de routage dans un bundle
# app/config/routing.yml
app:
resource: "@AppBundle/Resources/config/routing.yml"
Dans votre propre ensemble, vous pouvez configurer des itinéraires qui servent deux objectifs:
• Correspondance à une demande, de sorte que l'action correcte soit appelée pour la
demande.
• Générer une URL à partir des paramètres name et route.
# src/AppBundle/Resources/config/routing.yml
my_page:
path: /application/content/page/{parameter}
defaults:
_controller: AppBundle:Default:myPage
parameter: 42
requirements:
parameter: '\d+'
methods: [ GET, PUT ]
condition: "request.headers.get('User-Agent') matches '/firefox/i'"
La configuration du routage est incluse dans votre fichier app/config/config.yml , par défaut dans
le fichier app/config/routing.yml .
De là, vous pouvez accéder aux contrôleurs dotés d'une configuration de routage annotée:
# app/config/routing.yml
https://riptutorial.com/fr/home 23
app:
resource: "@AppBundle/Controller"
type: annotation
Dans votre propre ensemble, vous pouvez configurer des itinéraires qui servent deux objectifs:
• Correspondance à une demande, de sorte que l'action correcte soit appelée pour la
demande.
• Générer une URL à partir des paramètres name et route.
// src/AppBundle/Controller/DefaultController.php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
/**
* @Route("/application")
*/
class DefaultController extends Controller {
/**
* @Route("/content/page/{parameter}",
* name="my_page",
* requirements={"parameter" = "\d+"},
* defaults={"parameter" = 42})
* @Method({"GET", "PUT"})
*/
public function myPageAction($parameter)
{
// ...
}
}
Le contrôleur est annoté avec un itinéraire de préfixe , de sorte que tout itinéraire configuré dans
ce contrôleur sera ajouté en préfixe.
Notez que le paramètre est injecté dans l'action en tant que paramètre de fonction.
Traditionnellement, vous pouvez utiliser le routage pour mapper la demande avec le composant
de routage qui traitait les paramètres de demande et de réponse par le composant HttpFoundation
.
https://riptutorial.com/fr/home 24
De plus, un paramètre de route personnalisé peut être créé en utilisant FOSRestBundle pour
étendre les fonctionnalités par défaut du composant de routage.
Ceci est utile pour créer des routes REST, ce qui est très utile pour spécifier comment transférer
des données structurées comme un fichier XML ou json dans une requête (et une réponse).
use FOS\RestBundle\Controller\Annotations\FileParam;
/**
* @FileParam(
* name="",
* key=null,
* requirements={},
* default=null,
* description="",
* strict=true,
* nullable=false,
* image=false
* )
*/
https://riptutorial.com/fr/home 25
Chapitre 8: Répartiteur d'événements
Syntaxe
• $ dispatcher-> dispatch (string $ eventName, Event $ event);
• $ dispatcher-> addListener (string $ eventName, callable $ listener, int $ priority = 0);
• $ dispatcher-> addSubscriber (EventSubscriberInterface $ abonné);
Remarques
• Il est souvent préférable d'utiliser une seule instance de EventDispatcher dans votre
application que vous injectez dans les objets devant déclencher des événements.
• Il est recommandé d’avoir un seul emplacement où vous gérez la configuration et d’ajouter
des écouteurs d’événement à votre EventDispatcher. Le framework Symfony utilise le
conteneur d'injection de dépendances.
• Ces modèles vous permettront de changer facilement vos écouteurs d'événement sans avoir
à modifier le code d'un module qui distribue des événements.
• Le découplage de la répartition des événements de la configuration de l'écouteur
d'événements est ce qui rend le Symfony EventDispatcher si puissant
• EventDispatcher vous aide à satisfaire le principe ouvert / fermé.
Examples
Démarrage rapide du répartiteur d'événements
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\GenericEvent;
// you may store this in a dependency injection container for use as a service
$dispatcher = new EventDispatcher();
// you can attach listeners to specific events directly with any callable
$dispatcher->addListener('an.event.occurred', function(Event $event) {
// process $event
});
https://riptutorial.com/fr/home 26
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\Event;
// you can attach event subscribers, which allow a single object to subscribe
// to many events at once
$dispatcher->addSubscriber(new class implements EventSubscriberInterface {
public static function getSubscribedEvents()
{
// here we subscribe our class methods to listen to various events
return [
// when anything fires a "an.event.occurred" call "onEventOccurred"
'an.event.occurred' => 'onEventOccurred',
// an array of listeners subscribes multiple methods to one event
'another.event.happened' => ['whenAnotherHappened', 'sendEmail'],
];
}
https://riptutorial.com/fr/home 27
Chapitre 9: Travailler avec des services Web
Examples
Rest Rest API
J'ai déjà écrit de la documentation sur ce site afin de décrire comment créer des services Web sur
Symfony
Nous pensons que nous avons un serveur Web installé sur une version configurée de Symfony
Framework . Vous devez avoir un compositeur (gestionnaire de paquets php) également installé.
Pour simplifier, si vous avez un composeur installé, tapez ceci dans une invite de terminal /
commande:
Cela créera un nouveau répertoire appelé "exemple" dans le répertoire actuel, avec une
installation standard du framework symfony.
Vous devez installer ces 2 bundles: JMSSerializer Bundle (étend le sérialiseur de composant de
structure) et FOSRest Bundle (étend le routage et les contrôleurs de composants de structure ...)
Tout d'abord, créez votre propre ensemble ("Example") (dans le répertoire Symfony):
Imaginez que nous voulions créer CRUD (Create / Read / Update / Delete) de cette entité
StackOverFlower:
# src/ExampleBundle/Resources/config/doctrine/StackOverFlower.orm.yml
https://riptutorial.com/fr/home 28
ExampleBundle\Entity\StackOverFlower:
type: entity
table: stackoverflower
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 100
#app/config/config.yml
fos_rest:
format_listener:
rules:
- { path: '^/stackoverflower', priorities: ['xml', 'json'], fallback_format: xml,
prefer_extension: true }
- { path: '^/', priorities: [ 'text/html', '*/*'], fallback_format: html,
prefer_extension: true }
Faire un contrôleur:
#src/ExampleBundle/Controller/StackOverFlowerController.php
namespace ExampleBundle\Controller;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\Delete;
use ExampleBundle\Entity\StackOverFlower;
$id = $request->get('id');
$user = $this->getDoctrine()->getManager()-
>getRepository("ExampleBundle:StackOverFlower")->findOneBy(array('id' => $id));
https://riptutorial.com/fr/home 29
return $user;
}
/**
* validateAndPersistEntity
*
* @param StackOverFlower $user
* @param Boolean $delete
* @return View the view
*/
private function validateAndPersistEntity(StackOverFlower $user, $delete = false) {
$template = "ExampleBundle:StackOverFlower:example.html.twig";
$validator = $this->get('validator');
$errors_list = $validator->validate($user);
if (0 === count($errors_list)) {
$em = $this->getDoctrine()->getManager();
$em->flush();
$view = $this->view($user)
->setTemplateVar('user')
->setTemplate($template);
} else {
$errors = "";
foreach ($errors_list as $error) {
$errors .= (string) $error->getMessage();
}
$view = $this->view($errors)
->setTemplateVar('errors')
->setTemplate($template);
return $view;
}
/**
* newStackOverFlowerAction
*
* @Get("/stackoverflower/new/{name}")
*
* @param Request $request
* @return String
*/
public function newStackOverFlowerAction(Request $request)
{
$user = new StackOverFlower();
$user->setName($request->get('name'));
https://riptutorial.com/fr/home 30
$view = $this->validateAndPersistEntity($user);
return $this->handleView($view);
}
/**
* editStackOverFlowerAction
*
* @Get("/stackoverflower/edit/{id}/{name}")
*
* @param Request $request
* @return type
*/
public function editStackOverFlowerAction(Request $request) {
$user = $this->findStackOverFlowerByRequest($request);
if (! $user) {
$view = $this->view("No StackOverFlower found for this id:". $request->get('id'),
404);
return $this->handleView($view);
}
$user->setName($request->get('name'));
$view = $this->validateAndPersistEntity($user);
return $this->handleView($view);
}
/**
* deleteStackOverFlowerAction
*
* @Get("/stackoverflower/delete/{id}")
*
* @param Request $request
* @return type
*/
public function deleteStackOverFlowerAction(Request $request) {
$user = $this->findStackOverFlowerByRequest($request);
if (! $user) {
$view = $this->view("No StackOverFlower found for this id:". $request->get('id'),
404);
return $this->handleView();
}
return $this->handleView($view);
}
/**
* getStackOverFlowerAction
*
* @Get("/stackoverflowers")
*
* @param Request $request
* @return type
https://riptutorial.com/fr/home 31
*/
public function getStackOverFlowerAction(Request $request) {
$template = "ExampleBundle:StackOverFlower:example.html.twig";
$users = $this->getDoctrine()->getManager()-
>getRepository("ExampleBundle:StackOverFlower")->findAll();
if (0 === count($users)) {
$view = $this->view("No StackOverFlower found.", 404);
return $this->handleView();
}
$view = $this->view($users)
->setTemplateVar('users')
->setTemplate($template);
return $this->handleView($view);
}
}
Ne me dites pas que c'est un gros contrôleur, c'est pour l'exemple !!!
#src/ExampleBundle/Resources/views/StackOverFlower.html.twig
{% if errors is defined %}
{{ errors }}
{% else %}
{% if users is defined %}
{{ users | serialize }}
{% else %}
{{ user | serialize }}
{% endif %}
{% endif %}
Comme vous pouvez le voir dans la base de données, un nouvel utilisateur a été créé avec le
nom: "test".
Vous pouvez voir un exemple complet de ce code sur mon compte GitHub , une branche avec
plus de routes réelles ...
Voici un exemple très simple, ne le laissez pas dans un environnement de production, vous
devez protéger votre api avec apikey !!!
https://riptutorial.com/fr/home 32
Chapitre 10: Validation
Remarques
En fait, la validation de formulaire est basée sur un composant nommé " Validator Component ".
Vous pouvez souvent utiliser le service dédié si vous n'avez pas à afficher un formulaire dans un
modèle. Comme les API. Vous pouvez valider les données de la même manière, comme ceci:
$validator = $this->get('validator');
$errors = $validator->validate($author);
if (count($errors) > 0) {
/*
* Uses a __toString method on the $errors variable which is a
* ConstraintViolationList object. This gives us a nice string
* for debugging.
*/
$errorsString = (string) $errors;
}
Examples
Validation Symfony à l'aide d'annotations
framework:
validation: { enable_annotations: true }
• Créez un AppBundle/Entity entité dans AppBundle/Entity . Les validations sont effectuées avec
les annotations @Assert .
<?php
# AppBundle/Entity/Car.php
namespace AppBundle\Entity;
/**
* Car
*
* @ORM\Table(name="cars")
* @ORM\Entity(repositoryClass="AppBundle\Repository\CarRepository")
*/
https://riptutorial.com/fr/home 33
class Car
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=50)
* @Assert\NotBlank(message="Please provide a name")
* @Assert\Length(
* min=3,
* max=50,
* minMessage="The name must be at least 3 characters long",
* maxMessage="The name cannot be longer than 50 characters"
* )
* @Assert\Regex(
* pattern="/^[A-Za-z]+$/",
* message="Only letters allowed"
* )
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="number", type="integer")
* @Assert\NotBlank(message="Please provide a number")
* @Assert\Length(
* min=1,
* max=3,
* minMessage="The number field must contain at least one number",
* maxMessage="The number field must contain maximum 3 numbers"
* )
* @Assert\Regex(
* pattern="/^[0-9]+$/",
* message="Only numbers allowed"
* )
*/
private $number;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
https://riptutorial.com/fr/home 34
* @param string $name
*
* @return Car
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set number
*
* @param integer $number
*
* @return Car
*/
public function setNumber($number)
{
$this->number = $number;
return $this;
}
/**
* Get number
*
* @return integer
*/
public function getNumber()
{
return $this->number;
}
}
<?php
# AppBundle/Form/CarType.php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
https://riptutorial.com/fr/home 35
class CarType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, ['label'=>'Name'])
->add('number', IntegerType::class, ['label'=>'Number'])
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Car'
));
}
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use AppBundle\Entity\Car;
use AppBundle\Form\CarType;
https://riptutorial.com/fr/home 36
$form = $this->createForm(
CarType::class,
$car,
[
'action' => $this->generateUrl('app_car'),
'method'=>'POST',
'attr'=>[
'id'=>'form_car',
'class'=>'car_form'
]
]
);
$form->handleRequest($request);
return $this->render(
'AppBundle:Default:car.html.twig',[
'form'=>$form->createView()
]
);
}
}
{% extends '::base.html.twig' %}
{% block body %}
{{ form_start(form, {'attr': {'novalidate':'novalidate'}}) }}
{{ form_row(form.name) }}
{{ form_row(form.number) }}
<button type="submit">Go</button>
{{ form_end(form) }}
{% endblock %}
<?php
# AppBundle/Entity/Person.php
namespace AppBundle\Entity;
/**
* Person
https://riptutorial.com/fr/home 37
*/
class Person
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var int
*/
private $age;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Person
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set age
*
* @param integer $age
*
* @return Person
*/
public function setAge($age)
https://riptutorial.com/fr/home 38
{
$this->age = $age;
return $this;
}
/**
* Get age
*
* @return int
*/
public function getAge()
{
return $this->age;
}
}
• Créez les informations de mappage d'entité pour la classe d'entité. Si vous utilisez la
commande php bin/console doctrine:generate:entity Symfony php bin/console
doctrine:generate:entity , le code suivant sera généré automatiquement. Sinon, si vous
n'utilisez pas la commande, vous pouvez créer le code suivant à la main.
# AppBundle/Resources/config/doctrine/Person.orm.yml
AppBundle\Entity\Person:
type: entity
table: persons
repositoryClass: AppBundle\Repository\PersonRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: '50'
age:
type: integer
lifecycleCallbacks: { }
# AppBundle/Resources/config/validation/person.yml
AppBundle\Entity\Person:
properties:
name:
- NotBlank:
message: "Name is required"
- Length:
min: 3
max: 50
minMessage: "Please use at least 3 chars"
maxMessage: "Please use max 50 chars"
- Regex:
pattern: "/^[A-Za-z]+$/"
https://riptutorial.com/fr/home 39
message: "Please use only letters"
age:
- NotBlank:
message: "Age is required"
- Length:
min: 1
max: 3
minMessage: "The age must have at least 1 number in length"
maxMessage: "The age must have max 3 numbers in length"
- Regex:
pattern: "/^[0-9]+$/"
message: "Please use only numbers"
<?php
# AppBundle/Form/PersonType.php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Person'
));
}
https://riptutorial.com/fr/home 40
}
app_person:
path: /person
defaults: { _controller: AppBundle:Default:person }
<?php
# AppBundle/Controller/DefaultController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\Person;
use AppBundle\Form\PersonType;
$form = $this->createForm(
PersonType::class,
$person,
[
'action' => $this->generateUrl('app_person'),
'method'=>'POST',
'attr'=>[
'id'=>'form_person',
'class'=>'person_form'
]
]
);
$form->handleRequest($request);
return $this->render(
'AppBundle:Default:person.html.twig', [
'form'=>$form->createView()
]
);
}
}
{% extends '::base.html.twig' %}
{% block body %}
{{ form_start(form, {'attr': {'novalidate':'novalidate'}}) }}
{{ form_row(form.name) }}
{{ form_row(form.age) }}
https://riptutorial.com/fr/home 41
<button type="submit">Go</button>
{{ form_end(form) }}
{% endblock %}
https://riptutorial.com/fr/home 42
Crédits
S.
Chapitres Contributeurs
No
Asset Management
2 Aaron Belchamber, Orlando
avec Assetic
Formulaires
6 Alsatian
dynamiques
Répartiteur
8 Chris Tickner
d'événements
https://riptutorial.com/fr/home 43