Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Titouan Galopin Product Manager SymfonyInsight 2

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Symfony 4

Slide 5

Slide 5 text

Symfony 4 Versionnement sémantique 5

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

Symfony Flex

Slide 12

Slide 12 text

Symfony Flex composer create-project symfony/skeleton mydir 12

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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.

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

Symfony Flex composer require symfony/monolog-bundle 17

Slide 18

Slide 18 text

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.

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Symfony Flex composer req logger 22

Slide 23

Slide 23 text

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.

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

“ Mais comment ca marche ? 26

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Symfony Flex Le kernel découvre la configuration 29

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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é

Slide 35

Slide 35 text

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' ); }

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Le maker bundle

Slide 38

Slide 38 text

Le maker bundle composer require --dev maker 38

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

Webpack Encore

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Webpack Encore composer require --dev webpack 45

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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”

Slide 49

Slide 49 text

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”

Slide 50

Slide 50 text

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()

Slide 51

Slide 51 text

L’intégration dans les infrastructures modernes

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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)%'

Slide 61

Slide 61 text

L’injection de dépendances

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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) );

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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']

Slide 70

Slide 70 text

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']

Slide 71

Slide 71 text

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) !

Slide 72

Slide 72 text

L’injection de dépendances Autodiscovery + Autowiring 72

Slide 73

Slide 73 text

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/*'

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

L’injection de dépendances Defaults + Autoconfiguration 77

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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.)

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

86 Merci ! Venez me voir au stand Symfony ! ▪ Twitter : @titouangalopin ▪ Github : @tgalopin ▪ titouan.galopin@symfony.com