$30 off During Our Annual Pro Sale. View Details »

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

Sarah KHALIL

March 31, 2017
Tweet

More Decks by Sarah KHALIL

Other Decks in Technology

Transcript

  1. @saro0h
    Sarah Khalil
    Quoi de neuf dans depuis 1 an ?
    jeudi 30 mars 2017

    View Slide

  2. View Slide

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

    View Slide

  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 !

    View Slide

  5. https://speakerdeck.com/saro0h

    View Slide

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

    View Slide

  7. View Slide

  8. View Slide

  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

    View Slide

  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

    View Slide

  11. View Slide

  12. v3.3

    View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. Ce que nous allons aborder

    View Slide

  17. Ce que nous allons aborder
    Deprecations & Features
    1

    View Slide

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

    View Slide

  19. View Slide

  20. View Slide

  21. Deprecations
    J’en ai choisi 7

    View Slide

  22. Deprecations
    J’en ai choisi 7

    View Slide

  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

    View Slide

  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

    View Slide

  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.

    View Slide

  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

    View Slide

  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

    View Slide

  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.

    View Slide

  29. X-Status-Code

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  33. autowiring-types

    View Slide

  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;
    }
    // …
    }

    View Slide

  35. %

    View Slide

  36. MAIS

    View Slide

  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

    View Slide

  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

    View Slide

  39. On veut simplifier

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  43. Insensibilité à la casse des identifiants de services
    services:
    MyService:
    class: AppBundle\RandomClass
    services:
    myService:
    class: AppBundle\AnotherClass

    View Slide

  44. Features
    3.3
    J’en ai choisi 20

    View Slide

  45. Features
    3.3
    J’en ai choisi 20

    View Slide

  46. View Slide

  47. View Slide

  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 %}

    {{ message }}

    {% endfor %}
    {% endfor %}
    {% endif %}
    {% for label, messages in app.flashes %}
    {% for message in messages %}

    {{ message }}

    {% endfor %}
    {% endfor %}
    Avant Après
    1/20

    View Slide

  49. {% if app.session is not null and app.session.started %}
    {% for message in app.session.flashbag.get('notice') %}

    {{ message }}

    {% endfor %}
    {% endif %}
    {% for message in app.flashes('notice') %}

    {{ message }}

    {% endfor %}
    Avant Après
    Récupérer les flash messages plus
    facilement (2/3)
    1/20

    View Slide

  50. {% for label, messages in app.flashes(['warning', 'error']) %}
    {% for message in messages %}

    {{ message }}

    {% endfor %}
    {% endfor %}
    Récupérer les flash messages plus
    facilement (3/3)
    1/20

    View Slide

  51. Le username des utilisateurs in memory
    ne sont plus normalisés
    Avant
    [email protected]
    devenait
    [email protected]
    Après
    [email protected]
    reste
    [email protected]
    2/20

    View Slide

  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

    View Slide

  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

    View Slide

  54. XLiff linter
    $ bin/console lint:xliff
    5/20

    View Slide

  55. Recherche dans le contenu d’un
    dump()
    Dans la WebDebugToolbar
    Dans le profiler
    Dans une page
    6/20

    View Slide

  56. Nouveau data collector : cache
    7/20

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  65. Implémentation de la PSR-16 (2/2)
    getMultiple($values)
    setMultiple($values, $ttl = null)
    deleteMultiple($values)
    9/20

    View Slide

  66. WebserverBundle
    • Code déplacé
    • $ bin/console server:start trouve un port disponible pour vous !
    10/20

    View Slide

  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

    View Slide

  68. Beaucoup de nouveautés côté Dependency Injection

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  73. Implémentation de la PSR-11
    16/20

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  77. Déclaration de service : Configuration par défaut
    pour tout un fichier
    services:
    _defaults:
    public: false
    autowire: true
    foo:
    class: Foo
    17/20

    View Slide

  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

    View Slide

  79. Amélioration sur le panel config
    Avant
    18/20

    View Slide

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

    View Slide

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

    View Slide

  82. Une petite dernière
    pour la route

    View Slide

  83. README
    20/20

    View Slide

  84. View Slide

  85. 2 nouveaux
    composants


    View Slide

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

    View Slide

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

    View Slide

  88. Composant Dotenv
    • On se doute un peu de ce qu’il fait ;)
    • « Superb error messages to easily spot any issue »

    View Slide

  89. Composant Dotenv
    Charge, parse vos fichiers .env et popule vos variables d’environnement.

    View Slide

  90. 2 - 3 trucs à savoir

    View Slide

  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

    View Slide

  92. Introduction des features expérimentales
    • Pour assurer la rétrocompatibilité (BC break promise)
    • Certaines features
    • @experimental
    http://symfony.com/blog/experimental-features

    View Slide

  93. Make the Symfony ecosystem
    stronger and standardized

    View Slide

  94. Make the Symfony ecosystem
    stronger and standardized

    View Slide

  95. Make the Symfony ecosystem
    stronger and standardized

    View Slide

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

    View Slide

  97. View Slide

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

    View Slide

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

    View Slide

  100. ' (
    Merci Javi!

    View Slide

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

    View Slide

  102. View Slide

  103. Merci !
    @catlannister

    View Slide

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

    View Slide