[SymfonyLive Paris] Quoi de neuf depuis 1 an ?

[SymfonyLive Paris] Quoi de neuf depuis 1 an ?

Il y a un peu plus d'un an, en novembre 2015 la version 3.0 est sortie. Beaucoup de choses se sont passées depuis ! 71 blog posts pour vous tenir au courant de toutes les nouveautés, plus de 1300 pull requests, 2 nouvelles versions… Je suis sûre que vous avez dû manquer un petit quelque chose ! Nous allons revoir ensemble ce qui est arrivé ; passer en revue les fonctionnalités que vous auriez râtées ou les redécouvrir.

34ade09dd3d11004ca8ee4174fd3d6a2?s=128

Sarah KHALIL

March 31, 2017
Tweet

Transcript

  1. @saro0h Sarah Khalil Quoi de neuf dans depuis 1 an

    ? jeudi 30 mars 2017
  2. None
  3. Oh nice, ça fait belle lurette que je mate plus

    trop le blog sur symfony.com
  4. Oh nice, ça fait belle lurette que je mate plus

    trop le blog sur symfony.com Pinaise j’vais enfin pouvoir marquer comme lues toutes mes notifs Github !
  5. https://speakerdeck.com/saro0h

  6. https://speakerdeck.com/saro0h 3.1 & 3.2 + Community stuff

  7. None
  8. None
  9. • 4 nouvelles versions mineures : 3.0, 3.1, 3.2 et

    et et 3.3 • Une pelleté de releases : ± 70 versions 1 928 mergées 3455 ouvertes
  10. • 4 nouvelles versions mineures : 3.0, 3.1, 3.2 et

    et et 3.3 • Une pelleté de releases : ± 70 versions 1 928 mergées 3455 ouvertes
  11. None
  12. v3.3

  13. None
  14. None
  15. None
  16. Ce que nous allons aborder

  17. Ce que nous allons aborder Deprecations & Features 1

  18. Ce que nous allons aborder Deprecations & Features 1 2-3

    trucs à savoir 2
  19. None
  20. None
  21. Deprecations J’en ai choisi 7

  22. Deprecations J’en ai choisi 7

  23. On en a fini avec SYMFONY__ • SYMFONY__ ne sera

    plus interprété en version 4.x • Il faut utiliser : %env()% (à partir de 3.2.x) # app/config/parameters.yml parameters: database_host: '%env(DATABASE_HOST)%' env(DATABASE_HOST): localhost
  24. On en a fini avec SYMFONY__ • SYMFONY__ ne sera

    plus interprété en version 4.x • Il faut utiliser : %env()% (à partir de 3.2.x) # app/config/parameters.yml parameters: database_host: '%env(DATABASE_HOST)%' env(DATABASE_HOST): localhost Valeur par défaut
  25. cache:clear avec warmup • Version 4 : Faire en sorte

    qu’il soit possible de générer le cache complet pour exécuter l’application sur un système « read-only ». • Le warmup exécuté au moment du cache clear n’est pas aussi fiable que la commande cache:warmup.
  26. cache:clear avec warmup • Version 4 : Faire en sorte

    qu’il soit possible de générer le cache complet pour exécuter l’application sur un système « read-only ». • Le warmup exécuté au moment du cache clear n’est pas aussi fiable que la commande cache:warmup. $ ./bin/console cache:clear (--env=prod|dev) Avant
  27. cache:clear avec warmup • Version 4 : Faire en sorte

    qu’il soit possible de générer le cache complet pour exécuter l’application sur un système « read-only ». • Le warmup exécuté au moment du cache clear n’est pas aussi fiable que la commande cache:warmup. $ ./bin/console cache:clear (--env=prod|dev) Avant $ ./bin/console cache:clear --no-warmup (--env=prod|dev) $ ./bin/console cache:warmup (--env=prod|dev) Après
  28. Console.EXCEPTION • console.EXCEPTION : exception lancée dans Command::execute(). • Pour

    le reste, tout est traité dans un bloc try catch dans la méthode Command::doRunCommand(). • Impossible d’overrider la manière de gérer les exceptions dans ces cas là. • Désormais, un nouvel évènement est lancé, console.ERROR après ce try catch.
  29. X-Status-Code

  30. X-Status-Code use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Response; public function onKernelException(GetResponseForExceptionEvent $event) {

    $exception = $event->getException(); // 500 is the original status code; but the end user will get a 404 $response = new Response('...', 500, ['X-Status-Code' => 404]); // ... $event->setResponse($response); } Avant
  31. X-Status-Code use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Response; public function onKernelException(GetResponseForExceptionEvent $event) {

    $exception = $event->getException(); // 500 is the original status code; but the end user will get a 404 $response = new Response('...', 500, ['X-Status-Code' => 404]); // ... $event->setResponse($response); } Avant use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Response; public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); $response = new Response('...', 404); // ... $event->allowCustomResponseCode(); $event->setResponse($response); } Après
  32. Composant ClassLoader • Composer a pris le relais ! •

    Si vous utilisez PHP 7 (et la version 3.3), vous pouvez dores et déjà tester en supprimant la ligne dans votre front controller. $kernel->loadClassCache();
  33. autowiring-types

  34. Autowiring services: rot13_transformer: class: AppBundle\Rot13Transformer twitter_client: class: AppBundle\TwitterClient autowire: true

    namespace AppBundle; class Rot13Transformer implements TransformerInterface { // … } namespace AppBundle; class TwitterClient { private $transformer; public function __construct(TransformerInterface $transformer) { $this->transformer = $transformer; } // … }
  35. %

  36. MAIS

  37. services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class: AppBundle\AnotherTransformer autowiring_types: AppBundle\TransformerInterface twitter_client:

    class: AppBundle\TwitterClient autowire: true namespace AppBundle; class Rot13Transformer implements TransformerInterface { // … } namespace AppBundle; class TwitterClient { private $transformer; public function __construct(TransformerInterface $transformer) { $this->transformer = $transformer; } // … } namespace AppBundle; class AnotherTransformer implements TransformerInterface { // … } Autowiring
  38. services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class: AppBundle\AnotherTransformer autowiring_types: AppBundle\TransformerInterface twitter_client:

    class: AppBundle\TwitterClient autowire: true namespace AppBundle; class Rot13Transformer implements TransformerInterface { // … } namespace AppBundle; class TwitterClient { private $transformer; public function __construct(TransformerInterface $transformer) { $this->transformer = $transformer; } // … } namespace AppBundle; class AnotherTransformer implements TransformerInterface { // … } Autowiring Implémentation par défaut
  39. On veut simplifier

  40. autowiring-types services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class: AppBundle\AnotherTransformer autowiring_types: AppBundle\TransformerInterface

    twitter_client: class: AppBundle\TwitterClient autowire: true Avant
  41. autowiring-types services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class: AppBundle\AnotherTransformer autowiring_types: AppBundle\TransformerInterface

    twitter_client: class: AppBundle\TwitterClient autowire: true Avant services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class: AppBundle\AnotherTransformer alias: rot13_transformer public: false twitter_client: class: AppBundle\TwitterClient autowire: true Après
  42. autowiring-types Implémentation par défaut services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class:

    AppBundle\AnotherTransformer autowiring_types: AppBundle\TransformerInterface twitter_client: class: AppBundle\TwitterClient autowire: true Avant services: rot13_transformer: class: AppBundle\Rot13Transformer another_transformer: class: AppBundle\AnotherTransformer alias: rot13_transformer public: false twitter_client: class: AppBundle\TwitterClient autowire: true Après
  43. Insensibilité à la casse des identifiants de services services: MyService:

    class: AppBundle\RandomClass services: myService: class: AppBundle\AnotherClass ≠
  44. Features 3.3 J’en ai choisi 20

  45. Features 3.3 J’en ai choisi 20

  46. None
  47. None
  48. Récupérer les flash messages plus facilement (1/3) {% if app.session

    is not null and app.session.started %} {% for label, messages in app.session.flashbag.all %} {% for message in messages %} <div class="alert alert-{{ label }}"> {{ message }} </div> {% endfor %} {% endfor %} {% endif %} {% for label, messages in app.flashes %} {% for message in messages %} <div class="alert alert-{{ label }}"> {{ message }} </div> {% endfor %} {% endfor %} Avant Après 1/20
  49. {% if app.session is not null and app.session.started %} {%

    for message in app.session.flashbag.get('notice') %} <div class="alert alert-notice"> {{ message }} </div> {% endfor %} {% endif %} {% for message in app.flashes('notice') %} <div class="alert alert-notice"> {{ message }} </div> {% endfor %} Avant Après Récupérer les flash messages plus facilement (2/3) 1/20
  50. {% for label, messages in app.flashes(['warning', 'error']) %} {% for

    message in messages %} <div class="alert alert-{{ label }}"> {{ message }} </div> {% endfor %} {% endfor %} Récupérer les flash messages plus facilement (3/3) 1/20
  51. Le username des utilisateurs in memory ne sont plus normalisés

    Avant foo-bar@gmail.com devenait foo_bar@gmail.com Après foo-bar@gmail.com reste foo-bar@gmail.com 2/20
  52. Symfony\Bundle\FrameworkBundle\Controller\Controller • On encourage à utiliser le Symfony\Bundle\FrameworkBundle\Controller\AbstractController. • Fournit

    les même helpers que le Controller, mais ne donne plus accès au container via la méthode get(). • Encourager la déclaration explicite des dépendances dans son Controller. 3/20
  53. Workflow : Guard expression transitions: journalist_approval: guard: "is_fully_authenticated() and has_role('ROLE_JOURNALIST')

    or is_granted('POST_EDIT', subject)" from: wait_for_journalist to: approved_by_journalist publish: guard: "subject.isPublic()" from: approved_by_journalist to: published 4/20
  54. XLiff linter $ bin/console lint:xliff 5/20

  55. Recherche dans le contenu d’un dump() Dans la WebDebugToolbar Dans

    le profiler Dans une page 6/20
  56. Nouveau data collector : cache 7/20

  57. Plus besoin d’activer les bundles un à un Le but

    : installer les bundles / composants dont on a besoin. 8/20
  58. Plus besoin d’activer les bundles un à un Le but

    : installer les bundles / composants dont on a besoin. Avant 1. Tout est là (composants/bundles) 2. Activer les fonctionnalités un à un en config 8/20
  59. Plus besoin d’activer les bundles un à un Le but

    : installer les bundles / composants dont on a besoin. Avant 1. Tout est là (composants/bundles) 2. Activer les fonctionnalités un à un en config Installer ce dont on a besoin Après 8/20
  60. Plus besoin d’activer les bundles un à un Le but

    : installer les bundles / composants dont on a besoin. Avant 1. Tout est là (composants/bundles) 2. Activer les fonctionnalités un à un en config Installer ce dont on a besoin Après NB : Une nouvelle classe Symfony\Bundle\Fullstack pour vérifier si tout symfony est installé (plutôt que le mode composant par composant) 8/20
  61. use Symfony\Component\Cache\Adapter\FilesystemAdapter; $cache = new FilesystemAdapter(); Avant Après simple cache

    9/20 Implémentation de la PSR-16 (1/2)
  62. use Symfony\Component\Cache\Adapter\FilesystemAdapter; $cache = new FilesystemAdapter(); // sauvegarder un élément

    en cache $numProducts = $cache->getItem('stats.num_products'); $numProducts->set(4711); $cache->save($numProducts); // sauvegarder un élément en cache $cache->set('stats.num_products', 4711); Avant Après simple cache 9/20 Implémentation de la PSR-16 (1/2)
  63. use Symfony\Component\Cache\Adapter\FilesystemAdapter; $cache = new FilesystemAdapter(); // sauvegarder un élément

    en cache $numProducts = $cache->getItem('stats.num_products'); $numProducts->set(4711); $cache->save($numProducts); // sauvegarder un élément en cache $cache->set('stats.num_products', 4711); Avant Après // récupérer un élément du cache $numProducts = $cache->getItem('stats.num_products'); if (!$numProducts->isHit()) { // ... item does not exist in the cache } else { $total = $numProducts->get(); } // récupérer un élément du cache if (!$cache->has('stats.num_products')) { // ... item does not exist in the cache } else { $total = $cache->get('stats.num_products'); } simple cache 9/20 Implémentation de la PSR-16 (1/2)
  64. use Symfony\Component\Cache\Adapter\FilesystemAdapter; $cache = new FilesystemAdapter(); // sauvegarder un élément

    en cache $numProducts = $cache->getItem('stats.num_products'); $numProducts->set(4711); $cache->save($numProducts); // sauvegarder un élément en cache $cache->set('stats.num_products', 4711); Avant Après // récupérer un élément du cache $numProducts = $cache->getItem('stats.num_products'); if (!$numProducts->isHit()) { // ... item does not exist in the cache } else { $total = $numProducts->get(); } // récupérer un élément du cache if (!$cache->has('stats.num_products')) { // ... item does not exist in the cache } else { $total = $cache->get('stats.num_products'); } // supprimer un élément du cache $cache->deleteItem('stats.num_products'); // supprimer un élément du cache $cache->delete('stats.num_products'); simple cache 9/20 Implémentation de la PSR-16 (1/2)
  65. Implémentation de la PSR-16 (2/2) getMultiple($values) setMultiple($values, $ttl = null)

    deleteMultiple($values) 9/20
  66. WebserverBundle • Code déplacé • $ bin/console server:start trouve un

    port disponible pour vous ! 10/20
  67. Log automatique des erreurs console • Le listener se repose

    sur le standard PSR-3 pour la sortie. • Il suffit de configurer monolog pour adapter la sortie. 11/20
  68. Beaucoup de nouveautés côté Dependency Injection

  69. FQCN comme id de service services: app.manager.user: class: AppBundle\EventListener\UserManager tags:

    ['kernel.event_subscriber'] services: AppBundle\EventListener\UserManager: tags: ['kernel.event_subscriber'] use AppBundle\EventListener\UserManager; // ... public function editAction() { $this->get(UserManager::class)->save($user); } Avant Après use AppBundle\EventListener\UserManager; // ... public function editAction() { $this->get('app.manager.user')->save($user); } 12/20
  70. La vie sans bundle Kernel::build() Enregistrer de la configuration Enregistrer

    les compiler pass Plus besoin d’enregistrer une classe de bundle 13/20
  71. Importer un ensemble de fichiers de configuration imports: - {

    resource: "*.yml" } - { resource: "common/**/*.xml" } - { resource: "/etc/myapp/*.{yml,xml}" } - { resource: "bundles/*/{xml,yaml}/services.{yml,xml}" } glob pattern 14/20
  72. Arguments nommés use Doctrine\ORM\EntityManager; use Psr\Log\LoggerInterface; namespace Acme; class NewsletterManager

    { private $logger; private $apiKey; public function __construct(LoggerInterface $logger, $apiKey) { $this->logger = $logger; $this->apiKey = $apiKey; } } services: newsletter_manager: class: Acme\NewsletterManager arguments: $apiKey: "%mandrill_api_key%" autowire: true 15/20
  73. Implémentation de la PSR-11 16/20

  74. Implémentation de la PSR-11 Symfony\Component\DependencyInjection\ContainerInterface étend la Psr\Container\ContainerInterface 16/20

  75. Implémentation de la PSR-11 Symfony\Component\DependencyInjection\ContainerInterface étend la Psr\Container\ContainerInterface get() &

    has() 16/20
  76. Implémentation de la PSR-11 Symfony\Component\DependencyInjection\ContainerInterface étend la Psr\Container\ContainerInterface get() &

    has() 2 nouvelles Exceptions : ContainerExceptionInterface & NotFoundExceptionInterface 16/20
  77. Déclaration de service : Configuration par défaut pour tout un

    fichier services: _defaults: public: false autowire: true foo: class: Foo 17/20
  78. Remplacement des wildcards pour les méthodes lors de l’autowiring services:

    _defaults: public: false autowire: ['set*'] foo: class: Foo Avant Après services: _defaults: public: false autowire: true foo: class: Foo Et class Foo { //… /** * @required */ public function setBar(Bar $bar) { // devrait être appelé } } https://github.com/symfony/symfony/pull/21763 bonus
  79. Amélioration sur le panel config Avant 18/20

  80. Amélioration sur le panel config Avant Après 18/20

  81. Amélioration sur le panel config 19/20

  82. Une petite dernière pour la route

  83. README 20/20

  84. None
  85. 2 nouveaux composants

  86. Composant Lock Gestion avancée du lock dans de nombreux systèmes

    (fichiers, redis, memcache). Ping Fabien Bourigault !
  87. Composant Lock Gestion avancée du lock dans de nombreux systèmes

    (fichiers, redis, memcache). Ping Fabien Bourigault !
  88. Composant Dotenv • On se doute un peu de ce

    qu’il fait ;) • « Superb error messages to easily spot any issue »
  89. Composant Dotenv Charge, parse vos fichiers .env et popule vos

    variables d’environnement.
  90. 2 - 3 trucs à savoir

  91. Symfony Demo 1.0.0 • Référence en matière de bonnes pratiques

    • Fork pour reproduire les bugs • Benchmark de performances • Montrer ce qui est possible avec http://symfony.com/blog/symfony-demo-1-0-0-released
  92. Introduction des features expérimentales • Pour assurer la rétrocompatibilité (BC

    break promise) • Certaines features • @experimental http://symfony.com/blog/experimental-features
  93. Make the Symfony ecosystem stronger and standardized

  94. Make the Symfony ecosystem stronger and standardized

  95. Make the Symfony ecosystem stronger and standardized

  96. Topics sur Github http://symfony.com/blog/standardizing-the-github-topics-for-symfony-repositories 2-3 règles à suivre par là

  97. None
  98. Sans lui, nous passerions notre temps là dessus…

  99. Sans lui, nous passerions notre temps là dessus…

  100. ' ( Merci Javi!

  101. Un grand merci à toute cette communauté au topzer !

    '
  102. None
  103. Merci ! @catlannister

  104. Merci ! @catlannister *NB : Symfony 4 requerra PHP 7