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

What’s a typical Symfony 4.2 application like?

What’s a typical Symfony 4.2 application like?

Symfony's configuration system has improved a lot in recent years. Version 4.2 brings a lot of minor improvements that all together give an even better developer experience. Let's step back and look at how we can tackle all of the most common problems using the new approaches! This will include tricks for configuring services as easily as possible, handling different environment configuration and the hugely important topic of environment variables and secrets. Best of all, we'll discuss some strategies to migrate your existing apps so you're never going to be left behind.

Nicolas Grekas

March 26, 2019

More Decks by Nicolas Grekas

Other Decks in Technology


  1. application like? What’s a typical

  2. @nicolasgrekas

  3. Stability and predictability are king!

  4. A Symfony Application is built around a Runtime configurable compiled

    container @nicolasgrekas
  5. SOLID principles @nicolasgrekas

  6. reproducible-builds.org @nicolasgrekas

  7. 12factor.net @nicolasgrekas

  8. @nicolasgrekas Big, explicit YAML files Big, explicit XML files 3rd

    Party Bundles Our App
  9. @nicolasgrekas <service id="twig" class="Twig\Environment" public="true"> <argument type="service" id="twig.loader" /> <argument

    /> <!-- Twig options --> <call method="addGlobal"> <argument>app</argument> <argument type="service" id="twig.app_variable" /> </call> <call method="addRuntimeLoader"> <argument type="service" id="twig.runtime_loader" /> </call> </service>
  10. services: app.spooky_word_generator: class: App\SpookyWordGenerator app.halloween_costume_creator: class: App\HalloweenCostumeCreator arguments: ['@app.spooky_word_generator'] app.candy_aggregator:

    class: App\CandyAggregator arguments: - '@app.halloween_costume_creator' - '%kernel.project_dir%' app.doorbell_ring_event_subscriber: class: App\DoorbellRingEventSubscriber tags: ['kernel.event_subscriber']
  11. services: _defaults: autowire: true autoconfigure: true public: false App\: resources:

    ../src services.yaml
  12. services: _defaults: autowire: true autoconfigure: true public: false $container->get(‘my_service’) is

    dead! Extend from AbstractController now!
  13. @nicolasgrekas Symfony 4 spirit Keep coding features By automating your

    configuration and providing you with great error messages
  14. Don’t hack the conventions doing code Keep writing configuration for

    the exceptions to the rules @weaverryan
  15. services: _defaults: autowire: true autoconfigure: true public: false bind: $projectRoot:

  16. services: _defaults: autowire: true autoconfigure: true public: false bind: string

    $projectRoot: '%kernel.project_dir%' Stricter bindings
  17. services: _defaults: autowire: true autoconfigure: true public: false bind: Symfony\Contracts\Cache\CacheInterface

    $apiCache: '@api.cache' Works also for services
  18. services: Symfony\Contracts\Cache\CacheInterface $apiCache: '@api.cache' Named autowiring aliases

  19. services: Symfony\Contracts\Cache\CacheInterface $apiCache: '@api.cache' Your favorite bundles can provide some!

  20. bin/console debug:autowiring

  21. bin/console debug:autowiring Lists only autowiring aliases. They are the only

    useful services! \o/
  22. @weaverryan Environment Variables

  23. @weaverryan Our app needs a production API Key

  24. @weaverryan class DoorbellRingEventSubscriber { private $apiKey; public function __construct(string $apiKey)

    { $this->apiKey = $apiKey; } } services: _defaults: bind: $apiKey: 'ILOVECANDY' Classic problem: avoid hardcoding secret values!
  25. @weaverryan services: _defaults: bind: $apiKey: '%env(API_KEY)%' // how the compiled

    code looks $s = new DoorbellRingEventSubscriber(getenv('API_KEY')); API_KEY=ILOVECANDY
  26. Great! So environment vars are more secure than parameters.yml …right?

  27. Not Really @weaverryan But they are more flexible

  28. Let’s read from a Secrets File @weaverryan

  29. services: _defaults: bind: $apiKey: '%env(key:API_KEY:json:file:SECRETS_FILE)%' (see EnvProcessor) $secretsFile = getenv('SECRETS_FILE');

    $data = json_decode( file_get_contents($secretsFile) ); $s = new DoorbellRingEventSubscriber( $data['API_KEY'] );
  30. How do we define environment variables? @weaverryan

  31. @weaverryan Use real env vars from your OS! and .env

    files for defaults+local values
  32. @weaverryan .env .env.local .env.test .env.test.local .env files? commit gitignore commit

    gitignore defaults only local values defaults local values Real env vars are never overridden
  33. @weaverryan Better recipes Better defaults Better experience

  34. framework: session: cookie_secure: auto cookie_samesite: lax routing: utf8

  35. @weaverryan Upgrading a flex- enabled app?

  36. None
  37. $ git commit $ rm symfony.lock $ rm config/ -r

    $ rm src/ -r $ composer sync-recipes $ git diff
  38. $ composer sync-recipes --force $ git diff

  39. @weaverryan Upgrading a NON flex-enabled app?

  40. Fully explicit style is still OK

  41. composer req symfony/flex composer sync-recipes

  42. Bonus - advanced - slide @weaverryan

  43. services: App\MyHeavyConnection: tags: - { name: proxy, interface: App\MyConnectionInterface }

    Works with final classes! \o/
  44. services: App\MyBlockRender: arguments: - !tagged_locator { tag: block, index_by: block_name

    } App\SomeBlock: tags: { name: block, block_name: some_block } New in 4.3 use !tagged to get an iterator
  45. None
  46. @nicolasgrekas If you think Symfony is awesome Please tell the

    World! Thank you!