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

[SymfonyCon Berlin] A year of Symfony

Sarah KHALIL
December 03, 2016

[SymfonyCon Berlin] A year of Symfony

Last year, Symfony 3 was out right before the SymfonyCon. A lot happened! 52 blog posts to help you keep up with all new things, 1200+ pull requests, 2 new versions out… Well I'm sure you missed something. Let's review what happened during last year: basically we'll see and/or discover nice new features that appeared since the last SymfonyCon.

Sarah KHALIL

December 03, 2016
Tweet

More Decks by Sarah KHALIL

Other Decks in Technology

Transcript

  1. @saro0h
    Sarah Khalil
    A year of

    View Slide

  2. A year ago…

    View Slide

  3. View Slide

  4. View Slide

  5. 2 main axes in this
    conference

    View Slide

  6. 1. Community

    View Slide

  7. 1. Community

    View Slide

  8. 2. Features

    View Slide

  9. 2. Features

    View Slide

  10. 2. Features

    View Slide

  11. Community

    View Slide

  12. A week of Symfony
    Every week!

    View Slide

  13. A new core contributor
    Grégoire Pineau
    Merger on the Workflow component

    View Slide

  14. Pull requests
    1,282 merged
    2,411 opened

    View Slide

  15. Issues
    1,438 closed

    View Slide

  16. 57 versions
    2.6.x 1 version
    2.7.x 14 versions
    2.8.x 14 versions
    3.0.x 9 versions
    3.1.x 10 versions
    3.2.x 4 versions






    Releases

    View Slide

  17. New way of releasing Symfony
    • A new minor version every 6 months
    • in november and may, usually at the end of the month
    • A new major version every 2 years
    • released at the same time as the last minor version

    View Slide

  18. SymfonyLive
    Cancelled

    View Slide

  19. Virtual hackdays

    View Slide

  20. Documentation
    Mercury project,150 hours of great work.

    View Slide

  21. View Slide

  22. Getting started: all basics about
    developing apps with Symfony.

    View Slide

  23. Getting started: all basics about
    developing apps with Symfony.
    Components: all about the
    standalone Symfony libraries.
    Bundles:
    commonly used bundles when
    developing Symfony apps.
    Reference: Form types, DI tags &
    Symfony configuration.

    View Slide

  24. Getting started: all basics about
    developing apps with Symfony.
    Guides and tutorials: Everything
    else.
    Components: all about the
    standalone Symfony libraries.
    Bundles:
    commonly used bundles when
    developing Symfony apps.
    Reference: Form types, DI tags &
    Symfony configuration.

    View Slide

  25. http://symfony.com/blog/the-new-symfony-documentation-search-engine
    Wanna use Algolia?

    View Slide

  26. Influence of
    and many others…

    View Slide

  27. Influence of
    and many others…

    View Slide

  28. View Slide

  29. 3.1
    I chose 11 features

    View Slide

  30. View Slide

  31. Deprecation helper improvements
    Detection of deprecation are done thanks to the PHPUnit bridge.









    3.1

    View Slide

  32. « disabled »
    PHPUnit won’t list the deprecations ; avoid your test suite failing.
    Deprecation helper improvements
    Detection of deprecation are done thanks to the PHPUnit bridge.









    3.1

    View Slide

  33. « /Passing callable strings .*/ »
    Will be matched as a regular expression
    against the deprecation message.
    « disabled »
    PHPUnit won’t list the deprecations ; avoid your test suite failing.
    Deprecation helper improvements
    Detection of deprecation are done thanks to the PHPUnit bridge.









    3.1

    View Slide

  34. « 10 »
    Test suite will fail if 10 or more
    deprecations are triggered.
    « /Passing callable strings .*/ »
    Will be matched as a regular expression
    against the deprecation message.
    « disabled »
    PHPUnit won’t list the deprecations ; avoid your test suite failing.
    Deprecation helper improvements
    Detection of deprecation are done thanks to the PHPUnit bridge.









    3.1

    View Slide

  35. • Implementation of the PSR-6 - Caching interface standard.
    • Cache arbitrary content in your application.
    • Symfony components use it to improve their performances.
    New component: Cache 3.1
    class BlogController extends Controller
    {
    public function indexAction()
    {
    // create a new item and getting it from the cache
    $cachedCategories = $this->get('cache.app')->getItem('categories');
    if (!$cachedCategories->isHit()) {
    $categories = ... // fetch categories from the database
    $cachedCategories->set($categories);
    $this->get('cache.app')->save($cachedCategories);
    } else {
    $categories = $cachedCategories->get();
    }
    // ...
    }
    }
    Adapters for common backends
    Redis, APCu, Memcache…

    View Slide

  36. • Implementation of the PSR-6 - Caching interface standard.
    • Cache arbitrary content in your application.
    • Symfony components use it to improve their performances.
    New component: Cache 3.1
    class BlogController extends Controller
    {
    public function indexAction()
    {
    // create a new item and getting it from the cache
    $cachedCategories = $this->get('cache.app')->getItem('categories');
    if (!$cachedCategories->isHit()) {
    $categories = ... // fetch categories from the database
    $cachedCategories->set($categories);
    $this->get('cache.app')->save($cachedCategories);
    } else {
    $categories = $cachedCategories->get();
    }
    // ...
    }
    }
    Adapters for common backends
    Redis, APCu, Memcache…

    View Slide

  37. Display forwards and redirects in the
    WDT and the profiler
    3.1
    Forward Redirect

    View Slide

  38. Security profiler panel improvements 3.1

    View Slide

  39. Security profiler panel improvements 3.1

    View Slide

  40. WDT: Color coded HTTP status for ajax requests 3.1

    View Slide

  41. WDT: Color coded HTTP status for ajax requests 3.1

    View Slide

  42. Profiler: Silenced errors in logs 3.1

    View Slide

  43. Profiler: Filters in requests 3.1

    View Slide

  44. Profiler: Filters in requests 3.1

    View Slide

  45. YAML deprecation 3.1
    framework:
    secret: %secret%
    framework:
    secret: '%secret%'
    parameters:
    my_object: '!php/object:O:27:"AppBundle\Service\MyService":1:{s:1:"b";s:3:"foo";}'
    parameters:
    my_object: '!!php/object:O:27:"AppBundle\Service\MyService":1:{s:1:"b";s:3:"foo";}'

    View Slide

  46. Process: Input stream 3.1
    use Symfony\Component\Process\Process;
    $process = new Process('cat');
    $process->setInput('file.txt');
    $process->run();
    use Symfony\Component\Process\InputStream;
    $input = new InputStream();
    $input->write('foo');
    $process = new Process('my_script');
    $process->setInput($input);
    $process->
    start();
    // ... read process output or do other things
    $input->write('bar');
    // ... read process output or do other things
    $input->write('qux');
    $input->
    close();
    before
    Cannot provide more input
    now

    View Slide

  47. Process: Output stream 3.1
    Process::OUT
    Process::ERR
    or

    View Slide

  48. Process: Output stream 3.1
    Process::OUT
    Process::ERR
    or
    use Symfony\Component\Process\Process;
    $process = new Process('ls -lsa');
    $process->start();
    foreach ($process as $type => $data) {
    if ($process::OUT === $type) {
    echo $data."\n";
    } else {
    echo "[ERR] ".$data."\n";
    }
    }
    returns an
    iterator

    View Slide

  49. Process: Output stream 3.1
    Process::OUT
    Process::ERR
    or
    use Symfony\Component\Process\Process;
    $process = new Process('ls -lsa');
    $process->start();
    foreach ($process as $type => $data) {
    if ($process::OUT === $type) {
    echo $data."\n";
    } else {
    echo "[ERR] ".$data."\n";
    }
    }
    returns an
    iterator

    View Slide

  50. 3.2

    View Slide

  51. « Saisissez une citation ici. »

    View Slide

  52. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    class DefaultController extends Controller
    {
    public function downloadAction()
    {
    $pdfPath = $this->getParameter('dir.downloads').'/my_file.pdf';
    return $this->file($pdfPath, ‘my_new_filename.pdf’, ResponseHeaderBag::DISPOSITION_INLINE);
    }
    }
    New file method helper
    protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
    3.2

    View Slide

  53. YAML supports PHP constants
    parameters:
    # this is considered a regular string
    foo: PHP_INT_MAX
    # this is considered a PHP constant
    bar: !php/const:PHP_INT_MAX
    3.2

    View Slide

  54. Compiler pass improvements 1/2
    // in compiler pass before 3.2
    $warmers = array();
    foreach ($container->findTaggedServiceIds('kernel.cache_warmer') as $id => $attributes) {
    $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
    $warmers[$priority][] = new Reference($id);
    }
    krsort($warmers);
    $warmers = call_user_func_array('array_merge', $warmers);
    // since 3.2
    $warmers = $this->findAndSortTaggedServices('kernel.cache_warmer', $container);
    3.2

    View Slide

  55. Compiler pass improvements 2/2 3.2
    $container->addCompilerPass(new CustomPass(), PassConfig::TYPE_AFTER_REMOVING , 30 );
    Step
    Priority

    View Slide

  56. New form type: DateInterval 3.2
    ->add('remindEvery', DateIntervalType::class, array(
    'placeholder' => array('years' => 'Years', 'months' => 'Months', 'days' => 'Days'),
    'widget' => 'choice',
    // customize which text boxes are shown
    'with_years' => true,
    'with_months' => true,
    'with_days' => true,
    'with_hours' => false,
    ))

    View Slide

  57. Tagged cache
    $cache = new FilesystemAdapter();
    $review = $cache->getItem('reviews-'.$reviewId);
    $review->set('...');
    $review->tag(['reviews', 'products', 'product-'.$productId]);
    $cache->save($review);
    //…
    // the HTML structure of reviews has changed:
    // invalidate all reviews
    $cache->invalidateTags('reviews');
    // instead of
    $cache->deleteItem('reviews-'.$reviewId);
    3.2

    View Slide

  58. Routing improvement 3.2
    // generating a URL with a fragment
    $this->get('router')->generate('user_settings', ['_fragment' => 'password']);
    /settings#password
    // route definition
    /**
    * @Route("/settings", defaults={"_fragment" = "password"}, name="user_settings")
    */
    public function settingsAction() { ... }

    View Slide

  59. YAML deprecations
    • No more duplicated keys otherwise you’ll get a ParseException
    3.2
    parameters:
    foo: bar
    parameters:
    key: 'aaa'
    # ...
    key: 'bbb'
    • Always put a space after colon otherwise you’ll get a ParseException

    View Slide

  60. Runtime Environment variable
    What’s new?
    • No longer obliged to prefix them by SYMFONY__
    • The value is resolved at runtime! (the app has the updated value)
    3.2
    doctrine:
    dbal:
    # ...
    password: "%env(DB_PASSWORD)%"
    To set default value and avoid not set env variable:
    parameters:
    env(DB_PASSWORD): s3cr3t_p4ssw0rd

    View Slide

  61. Console improvements 3.2
    $output->writeln('Test>');
    Multiple text style options
    Hidden commands namespace AppBundle\Command;
    use Symfony\Component\Console\Command\Command;
    class FooCommand extends Command
    {
    protected function configure()
    {
    $this
    ->setName('app:foo')
    // ...
    ->setHidden(true)
    ;
    }
    }

    View Slide

  62. Serializer: CSV encoder 3.2
    // instantiation, when using it inside the Symfony framework
    $serializer = $container->get('serializer');
    $data = [
    'foo' => 'aaa',
    'bar' => [
    ['id' => 111, 1 => 'bbb'],
    ['lorem' => 'ipsum'],
    ]
    ];
    file_put_contents(
    'data.csv',
    $container->get('serializer')->encode($data, 'csv')
    );
    // decoding CSV contents
    $data = $serializer->decode(file_get_contents('data.csv'), 'csv');

    View Slide

  63. Serializer: YAML encoder 3.2
    $obj = new \stdClass();
    $obj->bar = 2;
    $data = $this->container->get('serializer')->encode(
    ['foo' => $obj],
    'yaml'
    // these are the default values applied by the encoder
    ['yaml_inline' => 1, 'yaml_indent' => 4, 'yaml_flags' => 0]
    );
    // $data = ' foo: !php/object:O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}\n';
    $data = $this->container->get('serializer')->decode(
    'foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}',
    'yaml'
    );
    // $data = ['foo' => $obj];

    View Slide

  64. Cache improvements 3.2

    View Slide

  65. Get information about the firewall 1/2
    • Symfony\Bundle\SecurityBundle\Security\FirewallConfig
    • name, provider, context, entrypoint, access denied URL…
    3.2

    View Slide

  66. Get information about the firewall 2/2 3.2

    View Slide

  67. Get information about the firewall 2/2 3.2

    View Slide

  68. Translation improvements
    // Before
    $this->get('translator')
    ->transChoice('1 apple|%count% apples', 7, ['%count%' => 7]);
    // After
    $this->get('translator')
    ->transChoice('1 apple|%count% apples', 7);
    3.2
    ./bin/console translation:update en --force --domain=admin

    View Slide

  69. Support for PhpStorm links (\o/) 3.2
    # app/config/config.yml
    framework:
    ide: 'phpstorm://open?file=%%f&line=%%l

    View Slide

  70. Source link 3.2

    View Slide

  71. Unicode routing support
    UTF-8 characters in route paths and requirements
    /**
    * @Route(
    * "/category/{name}",
    * "requirements" = { "name": "䴰ᬨ|بيحرت" }
    * "options" = { "utf8": true }
    * )
    */
    public function categoryAction($name)
    {
    // ...
    }
    /category/䴰ᬨ, /category/بيحرت
    3.2

    View Slide

  72. Unicode routing support
    UTF-8 characters in route paths and requirements
    /**
    * @Route(
    * "/category/{name}",
    * "requirements" = { "name": "䴰ᬨ|بيحرت" }
    * "options" = { "utf8": true }
    * )
    */
    public function categoryAction($name)
    {
    // ...
    }
    /category/䴰ᬨ, /category/بيحرت
    not needed before 4.0
    is able to detect UTF-8
    3.2

    View Slide

  73. • Implementation of the petri net (Transitions, places…)
    • Supports state machine
    New component: Workflow 3.2

    View Slide

  74. • Implementation of the petri net (Transitions, places…)
    • Supports state machine
    New component: Workflow
    https://speakerdeck.com/lyrixx/le-reveil-du-workflow
    3.2

    View Slide

  75. • Implementation of the petri net (Transitions, places…)
    • Supports state machine
    New component: Workflow
    https://speakerdeck.com/lyrixx/le-reveil-du-workflow
    https://speakerdeck.com/tucksaun/symfonylive-london-2016-the-workflow-awakens
    3.2

    View Slide

  76. • Implementation of the petri net (Transitions, places…)
    • Supports state machine
    New component: Workflow
    https://speakerdeck.com/lyrixx/le-reveil-du-workflow
    https://speakerdeck.com/tucksaun/symfonylive-london-2016-the-workflow-awakens
    https://speakerdeck.com/saro0h/openclassrooms-workflow-component
    3.2

    View Slide

  77. Better support for one command
    applications
    3.2
    use Symfony\Component\Console\Application;
    $command = new \FooCommand();
    $application = new Application();
    $application->add($command);
    // the second boolean argument tells if this is a single-command app
    $application->setDefaultCommand($command->getName(), true);
    // this now executes the 'FooCommand' without passing its name
    $application->run();

    View Slide

  78. Simpler command testing 3.2
    use Symfony\Component\Console\Tester\CommandTester;
    $commandTester = new CommandTester($command);
    $helper = $command->getHelper('question');
    $helper->setInputStream($this->getInputStream("123\nfoo\nbar\n"));
    protected function getInputStream($input)
    {
    $stream = fopen('php://memory', 'r+', false);
    fputs($stream, $input);
    rewind($stream);
    return $stream;
    }
    use Symfony\Component\Console\Tester\CommandTester;
    $commandTester = new CommandTester($command);
    $commandTester->setInputs(['123', 'foo', 'bar']);

    View Slide

  79. Thank you Javier. Without you… our life would be…

    View Slide

  80. Thank you Javier. Without you… our life would be…

    View Slide

  81. " #
    Thank you Javi!

    View Slide

  82. Big thank to this amazing community
    "

    View Slide

  83. See ya next year!
    @catlannister

    View Slide