diff --git a/developpement/symfony3/presentation/slides.md b/developpement/symfony3/presentation/slides.md index 11f6dc5..a5f9b40 100644 --- a/developpement/symfony3/presentation/slides.md +++ b/developpement/symfony3/presentation/slides.md @@ -1,4 +1,4 @@ - + # Remise à niveau Symfony3 ## William Petit - S.C.O.P. Cadoles @@ -58,7 +58,7 @@ symfony new 3.4 ### Les principaux répertoires et leur rôle |Répertoire|Rôle| -|:-:|:-:| +|:-|:-| |`app/config/`|Configuration de l'application| |`app/Resources/`|Depuis Symfony3, répertoire contenant les vues ainsi les "assets" de l'application| |`src/AppBundle/`|Sources de l'application| @@ -68,7 +68,7 @@ symfony new 3.4 ## Structuration d'un projet (2) |Répertoire|Rôle| -|:-:|:-:| +|:-|:-| |`tests/`|Répertoire contenant les tests de l'application (unitaire comme fonctionnels)| |`var/`|Répertoire contenant toutes les données "vivantes" de l'application| |`vendor/`| Dépendances Composer @@ -79,7 +79,7 @@ symfony new 3.4 ### Quelques commandes (très) utiles |Commande|Description| -|:-:|:-:| +|:-|:-| |`server:run`|Exécuter l'application avec le serveur HTTP PHP| |`security:check`|Vérifier que les dépendances du projet ne comportent pas de vulnérabilités connues| |`debug:container`|Retrouver le mapping services <-> classe PHP| @@ -90,7 +90,7 @@ symfony new 3.4 ### Les générateurs par défaut |Commande|Description| -|:-:|:-:| +|:-|:-| |`generate:bundle`|Créer un nouveau bundle| |`generate:controller`|Créer un nouveau contrôleur| |`generate:command`|Créer une nouvelle commande| @@ -247,7 +247,7 @@ class DemoController extends Controller ### Paramètres spéciaux |Paramètre|Description| -|:-:|:-:| +|:-|:-| |`_locale`| La "locale" utilisé par l'application pour la requête en cours | |`_format`| Le "format" utilisé par l'application pour la requête en cours | |`_controller`| L'identifiant du contrôleur et son action utilisés pour traiter la requête en cours| @@ -669,10 +669,316 @@ Implémenter une classe `Guard` pour créer un firewall pour un serveur d'authen ``` --- -## Étendre Twig +## Étendre Twig (1) +### Créer son extension +```php +// src/AppBundle/Twig/AppExtension.php +namespace AppBundle\Twig; +class AppExtension extends \Twig_Extension +{ + public function getFilters() + { + return [ + new \Twig_SimpleFilter('pad', [$this, 'pad']), + ]; + } + + public function pad( + $input, + $length, + $pattern = ' ', + $type = STR_PAD_LEFT + ) { + return str_pad($input, $length, $pattern, $type); + } + +} +``` + +--- + +## Étendre Twig (2) + +### Enregistrer l'extension comme service + +```yaml +// app/config/services.yml + +services: + + AppBundle\Twig\AppExtension: + tags: [ twig.extension ] +``` + +--- + +## Étendre Twig (3) + +### Utiliser le filtre + +```twig +

{{ "1" | pad(10, "0") }}

+``` + +--- + +# L'ORM Doctrine et le modèle de données + +## Configuration +## Migration du schéma +## Entités et dépôts +## Les évènements + +--- + +## Configuration + +--- + +## Migration du schéma (1) + +### En développement + +```bash +bin/console doctrine:schema:update --force +``` +--- + +## Migration du schéma (2) + +### En production + +1. Récupération du schéma de la base en production en version `[origine]` +2. Création d'un script de migration SQL en fonction des nouvelles entités de la version `[cible]` + ```bash + mkdir -p migrations + bin/console doctrine:schema:update \ + --dump-sql > migration-[origine]-[cible].sql + ``` +3. Vérification/modification manuelle du script de migration +4. Passage du script de migration validé en production + +--- + +## Entités et dépôts (1) + +### Génération d'entités + +```bash +bin/console doctrine:generate:entity +``` + +--- +## Entités et dépôts (2) + +### La classe de l'entité + +```php +/** + * Post + * @ORM\Table(name="post") + * @ORM\Entity( + * repositoryClass="AppBundle\Repository\PostRepository" + * ) + */ +class Post +{ + /** + * @var int + * @ORM\Column(name="id", type="integer") + * @ORM\Id + * @ORM\GeneratedValue(strategy="AUTO") + */ + private $id; + + /** + * @var string + * @ORM\Column(name="Content", type="text", nullable=true) + */ + private $content; + // [...] +} +``` +--- +## Entités et dépôts (3) + +### Les annotations de classe + +|Annotation|Paramètres (non exhaustifs)|Description| +|:-|:-|:-| +|`@ORM\Table`|`name`: nom de la table| Description de la table associée à la base de données| +|`@ORM\Entity`|`repositoryClass`: identifiant de la classe `EntityRepository` associée à cette entité| Métadonnées de contexte liées à l'entité| + +--- +## Entités et dépôts (4) + +### Les annotations d'attributs + +|Annotation|Paramètres (non exhaustifs)|Description| +|:-|:-|:-| +|`@ORM\Column`|`name`: nom de la colone, `type`: type de la colone, `nullable`| Description de la colonne dans la base de donnée associée à l'attribut| +|`@ORM\Id`|| Déclare l'attribut comme une clé primaire dans la table| +|`@ORM\GeneratedValue`|`strategy`: stratégie de génération de la valeur de l'attribut | Déclare l'attribut comme généré automatiquement par la base de donnée | + +--- +## Entités et dépôts (5) + +### Accéder aux gestionnaires d'entités dans un contrôleur + +```php +use Doctrine\Common\Persistence\ObjectManager; + +class DemoController extends Controller +{ + /** + * @Route("/demo") + */ + public function demoAction(ObjectManager $em) + { + // Faire quelque chose avec l'entité manager + } +} +``` + +--- + +## Entités et dépôts (6) + +### Enregistrer un nouvelle entité dans la base + +```php +use AppBundle\Entity\Post; + +// [...] +// La variable $em est récupéré en tant que service + +// On créait une instance de notre entité +$post = new \Post(); + +// On modifie les valeurs des attributs de notre instance +$post->setContent("hello world"); + +// On référence notre instance comme nouvelle entité à persister +$em->persist($post); + +// On fait appliquer à l'ORM les modifications de l'"unit of work" +$em->flush(); +``` + +--- + +## Entités et dépôts (7) + +### Modifier une entité existante + +```php +$repository = $em->getRepository(Post::class); + +// On récupère une instance de notre entité à +// partir de son identifiant depuis la base de données +$post = $repository->find($id); + +// On modifie les valeurs des attributs de notre instance +$post->setContent("foo bar"); + +// On fait appliquer à l'ORM les modifications de l'"unit of work" +$em->flush(); +``` + +--- + +## Entités et dépôts (8) + +### Supprimer une entité + +```php +$repository = $em->getRepository(Post::class); + +// On récupère une instance de notre entité à partir +// de son identifiant depuis la base de données +$post = $repository->find($id); + +$em->remove($post); + +// On fait appliquer à l'ORM les modifications de l'"unit of work" +$em->flush(); +``` +--- + +## Entités et dépôts (9) + +### Les relations: exemple `one to many` + +```php +use Doctrine\Common\Collections\ArrayCollection; + +class Post +{ + /** + * @var Doctrine\Common\Collections\ArrayCollection + * @ORM\OneToMany(targetEntity="Comment", mappedBy="post") + */ + private $comments; +} +``` +--- + +### Les relations: `one to many` +```php +class Comment +{ + /** + * @ORM\ManyToOne(targetEntity="Post", inversedBy="comments") + * @ORM\JoinColumn(name="post_id", referencedColumnName="id") + */ + private $post; +} +``` +--- + +## Les évènements Doctrine et Symfony (1) + +### Création du `Listener` + +```php +// src/AppBundle/EventListener/SearchIndexer.php +namespace AppBundle\EventListener; + +use Doctrine\ORM\Event\LifecycleEventArgs; +use AppBundle\Entity\Post; + +class PostUpdateNotifier +{ + public function postPersist(LifecycleEventArgs $args) + { + $entity = $args->getEntity(); + + if (!$entity instanceof Post) { + return; + } + + // Faire quelque chose avec le Post... + } +} +``` + +--- + +## Les évènements Doctrine et Symfony (2) + +### Référencer le service + +```yaml +// app/config/services.yml + +services: + AppBundle\EventListener\PostCreationNotifier: + tags: + - { name: doctrine.event_listener, event: postPersist } +``` --- # Les formulaires @@ -683,11 +989,113 @@ Implémenter une classe `Guard` pour créer un firewall pour un serveur d'authen --- -# L'ORM Doctrine et le modèle de données +## Création et traitement de formulaires (1) -## Concept d'ORM -## Entité et Dépôt -## Les évènements +### Générer les formulaires CRUD pour une entité +```bash +bin/console doctrine:generate:crud +``` + +--- + +### Exercice proposé + +Créer une micro application de type "TodoList". L'application devra comprendre une entité `Task` avec les attributs suivants: +- Un status: à faire | en cours | fermé +- Un texte de description +- Un label + +La mise à jour de l'état d'une tâche devra automatiquement déclencher l'envoi d'un courriel à une adresse donnée (fixe, paramétrée dans le fichier `parameters.yml` de l'application). + +**Ressources** + +- https://symfony.com/doc/3.4/email.html +- http://symfony.com/doc/3.4/doctrine/event_listeners_subscribers.html + +--- + +## Création et traitement de formulaires (2) + +### La classe `AbstractType` +### Construction des champs +### Définition des options +### Utilisation du formulaire dans le contrôleur +### Rendu du formulaire dans un template Twig + +--- + + +## Création et traitement de formulaires (3) + +### Formulaires en tant que services +#### Déclararation des dépendances +#### Déclarations du services + +```yaml +// app/config/services.yml +services: + App\Form\PostType: + tags: [form.type] +``` + +--- + +## Validation des données (1) + +### Installer le composant `validator` + +```bash +composer require validator +``` +### Configurer le composant +```yaml +# app/config/config.yml +framework: + validation: { enable_annotations: true } +``` +--- + +## Validation des données (2) + +### Les annotations `Àssert` + +```php +class MyEntity +{ + /** + * @Assert\NotBlank() + */ + public $name; +} +``` +Les différentes validations pré-existantes: `NotBlank`, `Blank`, `NotNull`, `IsNull`, `isTrue`, `IsFalse`, `Email`, `Url`... + +Voir http://symfony.com/doc/3.4/validation.html#supported-constraints + +--- + +## Validation des données (3) + +### Utilisation basique + +```php + +// On récupère le service "validator" +// depuis le conteneur de services +$validator = $this->get('validator'); + +$errors = $validator->validate($myObject); + +if ( count($errors) > 0 ) { + // Traiter les erreurs +} +``` + +--- + +## Validation des données (4) + +### Utilisation avec les formulaires --- @@ -698,6 +1106,10 @@ Implémenter une classe `Guard` pour créer un firewall pour un serveur d'authen --- +## Gestion des environnements + +--- + # Licence ## CC BY-NC-SA 3.0 FR diff --git a/developpement/symfony3/ressources/planning.ods b/developpement/symfony3/ressources/planning.ods index b36809e..4037312 100644 Binary files a/developpement/symfony3/ressources/planning.ods and b/developpement/symfony3/ressources/planning.ods differ