Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Symfony 4 : une nouvelle expérience de développement

Symfony 4 : une nouvelle expérience de développement

Titouan Galopin

October 25, 2018
Tweet

More Decks by Titouan Galopin

Other Decks in Programming

Transcript

  1. Symfony 4
    Une nouvelle expérience de
    développement
    Octobre 2018
    Forum PHP

    View Slide

  2. Titouan Galopin
    Product Manager
    SymfonyInsight
    2

    View Slide

  3. 3
    Agenda
    1. Symfony 4
    2. Symfony Flex
    3. Le maker bundle
    4. Webpack Encore
    5. L’intégration dans les infrastructures modernes
    6. L’injection de dépendances

    View Slide

  4. Symfony 4

    View Slide

  5. Symfony 4
    Versionnement sémantique
    5

    View Slide

  6. Symfony 4
    PHP 7.1+
    Migration 3 => 4 simplifiée par le système
    de dépréciations
    6

    View Slide

  7. Symfony 4
    Symfony 4 = Symfony 3.4
    sans la couche de compatibilité …
    7

    View Slide

  8. Symfony 4
    Symfony 4 = Symfony 3.4
    sans la couche de compatibilité …
    … mais aussi bien plus que ca !
    8

    View Slide

  9. Symfony 4
    Réévaluation de toutes les idées de Symfony pour les
    adapter au développement en 2018
    9

    View Slide

  10. Symfony 4
    Réévaluation de toutes les idées de Symfony pour les
    adapter au développement en 2018
    Plus facile à apprendre / configurer / utiliser / déployer
    Framework PHP le plus rapide du marché
    10
    phpbenchmarks.com

    View Slide

  11. Symfony Flex

    View Slide

  12. Symfony Flex
    composer create-project
    symfony/skeleton mydir
    12

    View Slide

  13. 13
    ├── bin/console
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/routing.yaml
    │ │ ├── framework.yaml
    │ │ ├── routing.yaml
    │ │ └── test/framework.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    ├── public/index.php
    └── src
    ├── Controller
    └── Kernel.php
    Nouvelle structure
    Projet minimal :
    - 13 fichiers
    - 4 dépendances directes

    View Slide

  14. 14
    ~ composer create-project symfony/skeleton mydir
    Installing symfony/skeleton (v4.1.5.3)
    - Installing symfony/skeleton (v4.1.5.3)
    Created project in mydir
    - Installing symfony/flex (v1.1.1)
    - ...
    Generating autoload files
    Symfony operations: 4 recipes (a4070919102626e6a1736d4d1896e8d8)
    - Configuring symfony/flex (>=1.0): From github.com/symfony/recipes:master
    - Configuring symfony/framework-bundle (>=3.3): From github.com/symfony/recipes:master
    - Configuring symfony/console (>=3.3): From github.com/symfony/recipes:master
    - Configuring symfony/routing (>=4.0): From github.com/symfony/recipes:master
    Executing script cache:clear [OK]
    Executing script assets:install public [OK]
    Some files may have been created or updated to configure your new packages.
    Please review, edit and commit them: these files are yours.

    View Slide

  15. Symfony Flex
    Plugin Composer
    Au moment de l’installation d’un package,
    Symfony Flex le configure automatiquement
    15

    View Slide

  16. Sans Flex
    - composer require bundle
    - Ajouter une ligne dans
    app/AppKernel.php
    - Créer la configuration dans
    app/config/config.yml
    - Importer le routing dans
    app/config/routing.yml
    Installation d’un bundle
    Avec Flex
    - composer require bundle
    16

    View Slide

  17. Symfony Flex
    composer require symfony/monolog-bundle
    17

    View Slide

  18. 18
    ~/mydir composer require symfony/monolog-bundle
    Restricting packages listed in "symfony/symfony" to "4.1.*"
    Using version ^3.3 for symfony/monolog-bundle
    Restricting packages listed in "symfony/symfony" to "4.1.*"
    Package operations: 3 installs, 0 updates, 0 removals
    - Installing monolog/monolog (1.23.0)
    - Installing symfony/monolog-bridge (v4.1.6)
    - Installing symfony/monolog-bundle (v3.3.0)
    Writing lock file
    Generating autoload files
    Symfony operations: 1 recipe (3ccbdff84ac79218c4bcf54d45c68b02)
    - Configuring symfony/monolog-bundle (>=3.1): From github.com/symfony/recipes:master
    Executing script cache:clear [OK]
    Executing script assets:install public [OK]
    Some files may have been created or updated to configure your new packages.
    Please review, edit and commit them: these files are yours.

    View Slide

  19. 19
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/monolog.yaml
    │ │ ├── prod/monolog.yaml
    │ │ └── test/monolog.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    └── public/index.php

    View Slide

  20. 20
    // config/bundles.php
    return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class
    => ['all' => true],
    Symfony\Bundle\MonologBundle\MonologBundle::class
    => ['all' => true],
    ];
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/monolog.yaml
    │ │ ├── prod/monolog.yaml
    │ │ └── test/monolog.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    └── public/index.php

    View Slide

  21. Symfony Flex
    Définit un écosystème à partir d’alias officiels
    21

    View Slide

  22. Symfony Flex
    composer req logger
    22

    View Slide

  23. 23
    ~/mydir composer req logger
    Restricting packages listed in "symfony/symfony" to "4.1.*"
    Using version ^3.3 for symfony/monolog-bundle
    Restricting packages listed in "symfony/symfony" to "4.1.*"
    Package operations: 3 installs, 0 updates, 0 removals
    - Installing monolog/monolog (1.23.0)
    - Installing symfony/monolog-bridge (v4.1.6)
    - Installing symfony/monolog-bundle (v3.3.0)
    Writing lock file
    Generating autoload files
    Symfony operations: 1 recipe (3ccbdff84ac79218c4bcf54d45c68b02)
    - Configuring symfony/monolog-bundle (>=3.1): From github.com/symfony/recipes:master
    Executing script cache:clear [OK]
    Executing script assets:install public [OK]
    Some files may have been created or updated to configure your new packages.
    Please review, edit and commit them: these files are yours.

    View Slide

  24. Symfony Flex
    Besoin d’un ORM ?
    composer req orm
    Besoin de Twig ?
    composer req twig
    24

    View Slide

  25. Symfony Flex
    Besoin d’une API ?
    composer req api
    Besoin d’une interface d’admin ?
    composer req admin
    25

    View Slide


  26. Mais comment ca marche ?
    26

    View Slide

  27. Symfony Flex
    Système de “recettes” : une recette par
    package
    27
    Un recette peut :
    - ajouter des variables d’env
    - ajouter des paramètres de container
    - ajouter des fichiers/dossiers au gitignore
    - créer des fichiers de configuration
    - enregistrer des bundles

    View Slide

  28. Symfony Flex
    Composition over Inheritance,
    pour votre projet complet !
    28

    View Slide

  29. Symfony Flex
    Le kernel découvre la configuration
    29

    View Slide

  30. 30
    ├── bin/console
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/routing.yaml
    │ │ ├── framework.yaml
    │ │ ├── routing.yaml
    │ │ └── test/framework.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    ├── public/index.php
    └── src
    ├── Controller
    └── Kernel.php

    View Slide

  31. 31
    ├── bin/console
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/routing.yaml
    │ │ ├── framework.yaml
    │ │ ├── routing.yaml
    │ │ └── test/framework.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    ├── public/index.php
    └── src
    ├── Controller
    └── Kernel.php
    Simple tableau associatif listant les bundles

    View Slide

  32. 32
    ├── bin/console
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/routing.yaml
    │ │ ├── framework.yaml
    │ │ ├── routing.yaml
    │ │ └── test/framework.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    ├── public/index.php
    └── src
    ├── Controller
    └── Kernel.php
    Simple tableau associatif listant les bundles
    Equivalent de AppKernel, charge les bons
    fichiers de configuration / services / routing

    View Slide

  33. 33
    ├── bin/console
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/routing.yaml
    │ │ ├── framework.yaml
    │ │ ├── routing.yaml
    │ │ └── test/framework.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    ├── public/index.php
    └── src
    ├── Controller
    └── Kernel.php
    Découverte automatique du contenu du dossier
    packages par le Kernel
    Simple tableau associatif listant les bundles
    Equivalent de AppKernel, charge les bons
    fichiers de configuration / services / routing

    View Slide

  34. 34
    ├── bin/console
    ├── config
    │ ├── bundles.php
    │ ├── packages
    │ │ ├── dev/routing.yaml
    │ │ ├── framework.yaml
    │ │ ├── routing.yaml
    │ │ └── test/framework.yaml
    │ ├── routes.yaml
    │ └── services.yaml
    ├── public/index.php
    └── src
    ├── Controller
    └── Kernel.php
    Découverte automatique du contenu du dossier
    packages par le Kernel
    Simple tableau associatif listant les bundles
    Equivalent de AppKernel, charge les bons
    fichiers de configuration / services / routing
    Chaque environnement peut avoir son
    sous-dossier dédié

    View Slide

  35. 35
    protected function configureContainer($container, loader) {
    $container->addResource(
    new FileResource($this->getProjectDir().'/config/bundles.php')
    );
    // ...
    $loader->load(
    $confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'
    );
    $loader->load(
    $confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob'
    );
    $loader->load(
    $confDir.'/{services}'.self::CONFIG_EXTS, 'glob'
    );
    $loader->load(
    $confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'
    );
    }

    View Slide

  36. Symfony Flex
    https://flex.symfony.com
    2 types de recettes :
    officielles et contrib
    36

    View Slide

  37. Le maker bundle

    View Slide

  38. Le maker bundle
    composer require --dev maker
    38

    View Slide

  39. Le maker bundle
    Un générateur
    qui fait bien les
    choses
    39
    make:auth
    make:command
    make:controller
    make:crud
    make:entity
    make:fixtures
    make:form
    make:functional-test
    make:migration
    make:serializer:encoder
    make:subscriber
    make:twig-extension
    make:unit-test
    make:user
    make:validator
    make:voter

    View Slide

  40. 40
    ~/mydir composer req annotations
    ~/mydir composer req --dev maker
    ~/mydir bin/console make:controller
    Choose a name for your controller class (e.g. OrangeJellybeanController):
    > HomeController
    created: src/Controller/HomeController.php
    _Success!_
    Next: Open your new controller class and add some pages!
    Nécessaire pour
    maker:controller

    View Slide

  41. Le maker bundle
    Le code généré vous appartient :
    Modifiez-le, adaptez-le, commitez-le !
    41

    View Slide

  42. Webpack Encore

    View Slide

  43. Webpack
    Regroupe des imports
    SASS/JS/TS/… pour créer
    un seul fichier
    43
    // app.js
    const ApiClient = require('./api/client');

    View Slide

  44. Webpack Encore
    Symfony Webpack Encore
    Librairie Javascript pour utiliser
    Webpack facilement
    44

    View Slide

  45. Webpack Encore
    composer require --dev webpack
    45

    View Slide

  46. 46
    ├── assets
    │ ├── css/app.css
    │ └── js/app.js
    ├── config/…
    ├── public
    │ ├── build/app.min.css
    │ ├── build/app.min.js
    │ └── index.php
    ├── src/...
    ├── package.json
    ├── webpack.config.js
    └── ...
    Dossier de source des assets

    View Slide

  47. 47
    ├── assets
    │ ├── css/app.css
    │ └── js/app.js
    ├── config/…
    ├── public
    │ ├── build/app.min.css
    │ ├── build/app.min.js
    │ └── index.php
    ├── src/...
    ├── package.json
    ├── webpack.config.js
    └── ...
    Dossier des assets minifiés
    Dossier de source des assets

    View Slide

  48. 48
    ├── assets
    │ ├── css/app.css
    │ └── js/app.js
    ├── config/…
    ├── public
    │ ├── build/app.min.css
    │ ├── build/app.min.js
    │ └── index.php
    ├── src/...
    ├── package.json
    ├── webpack.config.js
    └── ...
    Dossier des assets minifiés
    Dossier de source des assets
    “composer.json pour Javascript”

    View Slide

  49. 49
    ├── assets
    │ ├── css/app.css
    │ └── js/app.js
    ├── config/…
    ├── public
    │ ├── build/app.min.css
    │ ├── build/app.min.js
    │ └── index.php
    ├── src/...
    ├── package.json
    ├── webpack.config.js
    └── ...
    Dossier des assets minifiés
    Dossier de source des assets
    Configuration de Webpack
    “composer.json pour Javascript”

    View Slide

  50. 50
    var Encore = require('@symfony/webpack-encore');
    Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .addEntry('app', './assets/js/app.js')
    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    .enableVersioning(Encore.isProduction())
    // enables Sass/SCSS support
    //.enableSassLoader()
    // uncomment if you use TypeScript
    //.enableTypeScriptLoader()
    // uncomment if you're having problems with a jQuery plugin
    //.autoProvidejQuery()

    View Slide

  51. L’intégration dans les
    infrastructures
    modernes

    View Slide

  52. L’intégration dans les infrastructures modernes
    Deux types de caches
    52

    View Slide

  53. Deux types de cache
    53
    Cache système :
    - Container compilé
    - Templates Twig
    compilés
    - Metadata Doctrine
    ...
    Cache applicatif :
    Vos données à mettre en
    cache

    View Slide

  54. Deux types de cache
    54
    Cache système :
    Ne change pas au cours de
    la vie de l’application
    (read-only)
    Cache applicatif :
    Change au cours de la vie
    de l’application

    View Slide

  55. Deux types de cache
    55
    Cache système :
    N’a pas besoin d’être
    synchronisé entre plusieurs
    instances frontales
    Cache applicatif :
    Doit être synchronisé entre
    plusieurs instances
    frontales

    View Slide

  56. Deux types de cache
    56
    Cache système :
    Filesystem
    Cache applicatif :
    Votre backend
    (Redis, PDO, …)

    View Slide

  57. Deux types de cache
    57
    framework:
    cache:
    app: cache.adapter.redis
    default_redis_provider: 'redis://%env(REDIS_HOST)%'

    View Slide

  58. L’intégration dans les infrastructures modernes
    Les variables d’environnement
    58

    View Slide

  59. Les variables d’environnement
    .env
    Intégré dans les recettes
    Référençable dans la configuration / les services
    59

    View Slide

  60. 60
    .env
    ###> symfony/framework-bundle ###
    APP_ENV=dev
    APP_SECRET=95b679e8ee0683314cece8ea8126795d
    #TRUSTED_PROXIES=127.0.0.1,127.0.0.2
    #TRUSTED_HOSTS=localhost,example.com
    ###< symfony/framework-bundle ###
    config/packages/framework.yaml
    framework:
    secret: '%env(APP_SECRET)%'

    View Slide

  61. L’injection de
    dépendances

    View Slide

  62. L’injection de dépendances
    Probablement le composant qui a le plus changé en 3.4/4.0
    62
    - Autodiscovery
    - Autowiring
    - Autoconfiguration
    - Defaults
    - Bindings
    - Services taggués
    - Controllers as services

    View Slide

  63. Comment fonctionne le composant DependencyInjection ?
    63
    class Persister {/* ... */}
    class Mailer {/* ... */}
    class RegistrationManager
    {
    private $persister;
    private $mailer;
    public function __construct(
    Persister $persister,
    Mailer $mailer
    ) { /* ... */ }
    public function register() {}
    }
    Objectif :
    $manager = new RegistrationManager(
    new Persister($doctrine),
    new Mailer($twig, $swiftmailer)
    );

    View Slide

  64. Comment fonctionne le composant DependencyInjection ?
    64
    Mailer Persister
    RegistrationManager
    Swiftmailer Twig Doctrine

    View Slide

  65. L’injection de dépendances
    Configuration => Graphe => Container compilé
    65

    View Slide

  66. L’injection de dépendances
    En Symfony 3, pour configurer ce graphe :
    app/config/services.yml
    66

    View Slide

  67. L’injection de dépendances
    Symfony 4 introduit différentes automatisations
    pour créer ce graphe plus simplement
    67

    View Slide

  68. L’injection de dépendances
    Identifiant de service = Nom complet de la classe
    68

    View Slide

  69. Identifiant de service = nom complet de la classe
    69
    Symfony 3
    app.mailer:
    class: AppBundle\Mailer\Mailer
    arguments: ['@twig', '@mailer']
    app.persister:
    class: AppBundle\Doctrine\Persister
    arguments: ['@doctrine']
    app.registration_manager:
    class: AppBundle\Registration\RegistrationManager
    arguments: ['@app.persister', '@app.mailer']

    View Slide

  70. Identifiant de service = nom complet de la classe
    70
    Symfony 4
    App\Mailer\Mailer:
    arguments: ['@twig', '@mailer']
    App\Doctrine\Persister:
    arguments: ['@doctrine']
    App\Registration\RegistrationManager:
    arguments: ['@App\Doctrine\Persister', '@App\Mailer\Mailer']

    View Slide

  71. Identifiant de service = nom complet de la classe
    71
    Symfony 4
    App\Mailer\Mailer:
    arguments: ['@twig', '@mailer']
    App\Doctrine\Persister:
    arguments: ['@doctrine']
    App\Registration\RegistrationManager:
    arguments: ['@App\Doctrine\Persister', '@App\Mailer\Mailer']
    Permet $container->get(Mailer::class) !

    View Slide

  72. L’injection de dépendances
    Autodiscovery + Autowiring
    72

    View Slide

  73. Autodiscovery + Autowiring
    73
    App\Mailer\Mailer:
    arguments: ['@twig', '@mailer']
    App\Doctrine\Persister:
    arguments: ['@doctrine']
    App\Registration\RegistrationManager:
    arguments: ['@App\Doctrine\Persister', '@App\Mailer\Mailer']
    App\:
    resource: '../src/*'

    View Slide

  74. Comment fonctionne le composant DependencyInjection ?
    74
    Mailer Persister
    RegistrationManager
    Swiftmailer Twig Doctrine
    Autodiscovery
    Autowiring

    View Slide


  75. L’autowiring n’a rien de magique
    Il est basé uniquement sur les noms
    de classes et des typehints
    75

    View Slide

  76. Comment fonctionne le composant DependencyInjection ?
    76
    class Persister {/* ... */}
    class Mailer {/* ... */}
    class RegistrationManager
    {
    private $persister;
    private $mailer;
    public function __construct(Persister $persister, Mailer $mailer)
    { /* ... */ }
    public function register() {}
    }
    Nom des services
    à injecter
    = typehints

    View Slide

  77. L’injection de dépendances
    Defaults + Autoconfiguration
    77

    View Slide

  78. Defaults + Autoconfiguration
    78
    services:
    _defaults:
    autowire: true
    autoconfigure: true
    public: false
    App\:
    resource: '../src/*'
    Defaults (par fichier) :
    Les nouvelles
    fonctionnalités
    sont opt-in
    Services privés
    par défaut

    View Slide

  79. Defaults + Autoconfiguration
    79
    services:
    _defaults:
    autowire: true
    autoconfigure: true
    public: false
    App\:
    resource: '../src/*'
    Defaults (par fichier) : Autoconfiguration :
    Configure
    automatiquement les
    services en fonctions de
    leurs interfaces (extensions
    Twig, listeners, etc.)

    View Slide

  80. L’injection de dépendances
    Bindings : et les paramètres ?
    80

    View Slide

  81. Bindings
    81
    services:
    # pour un service précis
    App\Registration\RegistrationManager:
    arguments:
    $projectDir: '%kernel.project_dir%'
    # pour tous les services du fichier
    _defaults:
    bind:
    $projectDir: '%kernel.project_dir%'
    Automatise
    l’injection des
    paramètres

    View Slide

  82. L’injection de dépendances
    Les contrôleurs sont des services
    82

    View Slide

  83. Controllers as services
    83
    services:
    App\Controller\:
    resource: '../src/Controller'
    tags: ['controller.service_arguments']
    public function contact(
    Request $request,
    Mailer $mailer
    ) {
    // …
    }
    Le tag permet
    d’injecter les
    services en
    paramètres de
    l’action

    View Slide

  84. Comment fonctionne le composant DependencyInjection ?
    84
    Mailer Persister
    RegistrationManager
    Swiftmailer Twig Doctrine
    RegistrationController

    View Slide

  85. 85
    Contribuez !
    symfony.com/support => Slack
    Pinguez Nicolas Grekas

    View Slide

  86. 86
    Merci !
    Venez me voir au stand Symfony !
    ▪ Twitter : @titouangalopin
    ▪ Github : @tgalopin
    [email protected]

    View Slide