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

Symfony4 Deep Dive

Symfony4 Deep Dive

Christian Flothmann

October 27, 2017
Tweet

More Decks by Christian Flothmann

Other Decks in Programming

Transcript

  1. License Symfony4 Deep Dive Copyright © 2017 SensioLabs – All

    Rights Reserved Contents are provided for strictly personal use. No part of these contents may be reproduced, stored in a retrieval system, publicly shared or transmitted in any form or by any means. Disclaimer Contents are distributed on an "as is" basis, without warranty. Although every precaution has been taken in the preparation of this work, neither the authors nor SensioLabs shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in this work.
  2. • LTS release (3 years of support) • Symfony 3.3

    + additional features + additional deprecations • release: November 2017 Symfony 3.4
  3. • standard release (8 months of support) • Symfony 3.3

    + additional features - deprecated features • release: November 2017 Symfony 4.0
  4. Version Release date End of Maintenance End of Life 2.8

    LTS 11/2015 11/2018 11/2019 3.3 05/2017 01/2018 07/2018 3.4 LTS 11/2017 11/2020 11/2021
  5. Version Release date End of Maintenance End of Life 2.8

    LTS 11/2015 11/2018 11/2019 3.3 05/2017 01/2018 07/2018 4.0 11/2017 07/2018 01/2019
  6. Symfony 2.x/3.x applications were based on the Symfony Standard Edition.

    The Symfony SE is shipped with all Symfony components and different bundles. The Symfony Standard Edition
  7. It ships with code that isn‘t used in all individual

    projects. The Symfony SE is often perceived as being „big“. Removing not needed functionality is a cumbersome task. The Symfony Standard Edition
  8. • Flex prefers composition over inheritance. • New project start

    with almost no dependencies. • Only needed features are added by developers. What is Symfony Flex?
  9. • hooks into the Composer workflow • automatically enables Symfony

    bundles • executes predefined recipes when packages are installed • recipes are removed when packages are uninstalled What is Symfony Flex?
  10. • The Symfony SE came with ready-to-use bundles and a

    sensible default config. • Adding new components/bundles and configuring them can be a complicated task. • Flex will automatically enable a bundle in all environments. How to add functions to a Flex project?
  11. • description of things to apply when a package is

    installed • maintained by the core team • stored in the symfony/recipes repository • automatically applied when the package is installed What is a recipe?
  12. • automatically enable a bundle in some/all environments • provide

    a reasonable default config • set some environment variables • copy files and create directories A recipe can
  13. Applying a recipe during installation $ composer require symfony/console Using

    version ^3.3 for symfony/console ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing symfony/console (v3.3.10): Downloading (100%) Writing lock file Generating autoload files Symfony operations: 1 recipe - Configuring symfony/console (3.3): From github.com/symfony/recipes:master Executing script make cache-warmup [OK] Executing script assets:install --symlink --relative public [OK]
  14. Applying a recipe during installation $ composer require symfony/console Using

    version ^3.3 for symfony/console ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing symfony/console (v3.3.10): Downloading (100%) Writing lock file Generating autoload files Symfony operations: 1 recipe - Configuring symfony/console (3.3): From github.com/symfony/recipes:master Executing script make cache-warmup [OK] Executing script assets:install --symlink --relative public [OK]
  15. Applying a recipe during installation $ composer require symfony/console Using

    version ^3.3 for symfony/console ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing symfony/console (v3.3.10): Downloading (100%) Writing lock file Generating autoload files Symfony operations: 1 recipe - Configuring symfony/console (3.3): From github.com/symfony/recipes:master Executing script make cache-warmup [OK] Executing script assets:install --symlink --relative public [OK]
  16. For common problems, Flex decides which is the best package

    to use. Use the alias to let Flex make the choice for you (e.g. admin, orm, etc.). Alternatives can still be installed using their full package name. Flex makes choices for you
  17. Aliases allow to reference packages from the Symfony namespace by

    their base name. Instead of symfony/foo you can just use foo (e.g. form instead of symfony/form). Aliases for Symfony components
  18. What is a pack? Packs are groups of several packages

    which all contribute to solve common problems. Developers only need to install one package instead of lots of packages.
  19. • Groups packages that are useful during development: • logging

    (Monolog) • profiling (WebProfilerBundle) • testing (PhpUnitBridge) Example: The debug pack
  20. • the core recipes repository is restricted to a limited

    set of packages • maintainers of other bundles cannot add their own recipes • the selection is opionated and the choice is made by the core team • only for MIT licensed packages Limitation of core recipes
  21. • are maintained by the community • can be created

    for MIT and Apache licensed packages • are not enabled by default Contrib recipes
  22. Activating contrib recipes in composer.json { "extra": { "symfony": {

    "id": "01BX217DNRHSWETJFT83M3XDE9", "allow-contrib": false } } }
  23. Activating contrib recipes in composer.json { "extra": { "symfony": {

    "id": "01BX217DNRHSWETJFT83M3XDE9", "allow-contrib": false } } }
  24. Activating contrib recipes in composer.json { "extra": { "symfony": {

    "id": "01BX217DNRHSWETJFT83M3XDE9", "allow-contrib": true } } }
  25. • will be applied to all services configured in the

    same file • can be overriden per service Default options per file services: _defaults: autowire: true autoconfigure: true public: false
  26. Autoconfiguration based on types Definitions can be modified based on

    parent classes/implemented interfaces. For example, bundles can add tags to definitions based on implemented interfaces.
  27. • the class attribute is optional • if omitted, the

    id will be treated as the FQCN Class based service ids services: AppBundle\Service\ExampleService: ~ # is equivalent to AppBundle\Service\ExampleService: class: AppBundle\Service\ExampleService
  28. • collects PHP classes based on glob patterns and PSR-4-compatible

    namespaces • some files/directories can be excluded PSR-4 based service configuration
  29. PSR-4 based service configuration services: App\: resource: '../src/*' # you

    can exclude directories or files # but if a service is unused, it's removed anyway #exclude: '../src/{Entity,Migrations,Repository,Tests}' exclude: '../src/{Entity}' # refine service definitions AppBundle\Service\ExampleService: arguments: # bind arguments that cannot be autowired $someArgument: 'some_value'
  30. Environment variables Warming up the application cache upfront requires all

    container parameters to be set. Some cloud hosting providers do not make these credentials available. Env var placeholders allow to inject and replace options at runtime.
  31. Usage of environment variables # defining default values for env

    var placeholders parameters: env(DB): 'sqlite://../../var/data.db' doctrine: dbal: url: '%env(DB)%'
  32. • strings may break type hints (e.g. a port number

    is expected to be an integer in PHP code) • to pass structured data (e.g. arrays) you need more env vars • reading from files for security reasons not possible Non-string environment variables
  33. • „bool:“, „int:“, „float:“, „string:“: perform type castings • „resolve:“:

    resolves container parameters • „base64:“, „json:“: decode data • „file:“: reads data from files „const:“ parses PHP constants Supported operators
  34. Full example parameters: # roughly equivalent to # "(int) getenv('DATABASE_PORT')"

    app.connection.port: '%env(int:DATABASE_PORT)%' project_dir: '/foo/bar' env(DB): 'sqlite://%%project_dir%%/var/data.db' db_dsn: '%env(resolve:DB)%' env(SECRETS_FILE): '/etc/secure/example.com/secrets.json' app.secrets: '%env(json:file:SECRETS_FILE)%' env(NUM_ITEMS): 'App\\Entity\\BlogPost::NUM_ITEMS' app.num_items: '%env(constant:NUM_ITEMS)%'
  35. Compute some data structures can be a time or memory

    consuming task. However, recalculating them on every request may not always be necessary. Caches can be used to share the same result between requests to save resources. The Cache component
  36. The PHP Framework Interoperability Group develops recommendations and interfaces for

    common problems that are solved by different frameworks. Standards are published as so-called PHP Standard Recommendations (PSRs). The PHP-FIG
  37. PSR-6 specifies a standard for a cache implementation. It describes

    interfaces that represent the cache data and its metadata as well as how to store data into and retrieve from the cache. PSR-6
  38. • encapsulates the data that should be cached • associates

    data with a key and expiration time • CacheItemInterface is specified by PSR-6 Cache items
  39. • cache pools are the gateway to write cache items

    into the cache and get them back via their key • CacheItemPoolInterface is specified by PSR-6 Cache pools
  40. • Cache adapters are Symfony‘s terminology for concrete cache backends.

    • They are never used directly be the end-user, but will only be configured once. • Developers only act with the cache through cache pools. Cache adapters
  41. The system cache pool is used internally by Symfony to

    cache framework related fragments (e.g. the serializer and validator caches). The system cache pool
  42. The app cache pool is meant to store application related

    data. It is not used automatically by the framework. Application developers must make use of the cache.app service to store data into and retrieve data from the app cache. The app cache pool will be used for autowiring by default. The app cache pool
  43. CacheItemInterface interface CacheItemInterface { public function getKey(); public function get();

    public function isHit(); public function set($value); public function expiresAt($expiration); public function expiresAfter($time); }
  44. CacheItemPoolInterface interface CacheItemPoolInterface { public function getItem($key); public function getItems(array

    $keys = array()); public function hasItem($key); public function clear(); public function deleteItem($key); public function deleteItems(array $keys); public function save(CacheItemInterface $item); public function saveDeferred(CacheItemInterface $item); public function commit(); }
  45. Storing cache items public function computeAndCache(CacheItemPoolInterface $cache) { $item =

    $cache->getItem('cache_key'); // compute some $value $item->set($value); $cache->save($item); }
  46. Retrieve cache items public function retrieveFromCache(CacheItemPoolInterface $cache): ?Value { $item

    = $cache->getItem('cache_key'); if ($item->isHit()) { return $item->get(); } return null; }
  47. Full example public function computeAndCache(CacheItemPoolInterface $cache) { $item = $cache->getItem('cache_key');

    // return the cached value if possible if ($item->isHit()) { return $item->get(); } // compute some $value $item->set($value); $cache->save($item) ; return $value; }
  48. Custom cache pools framework: cache: pools: # the "api" cache

    pool will be # available as the cache.api service api: adapter: memcached
  49. PSR-6 solves caching but is rather formal. It is more

    verbose than needed for many use cases. PSR-16 defines a streamlined interface for common cases. PSR-16
  50. The CacheInterface interface CacheInterface { public function get($key, $default =

    null); public function set($key, $value, $ttl = null); public function delete($key); public function clear(); public function getMultiple($keys, $default = null); public function setMultiple($values, $ttl = null); public function deleteMultiple($keys); public function has($key); }
  51. Full example public function computeAndCache(CacheInterface $cache) { if ($cache->has('cache_key')) {

    // return the cached value if possible return $cache->get('cache_key'); } // compute some $value $cache->set('cache_key', $value) ; return $value; }
  52. Introduction Workflows are processes in your application (for example, the

    publishing process of blog posts). They should be kept outside your code and be defined in your application config.
  53. Terms 1/1 • Place the states a workflow can be

    in • Transition an action that brings the workflow from one place into another
  54. Terms 2/2 • Definition the places of a workflow and

    the transitions to get from one place to another • Marking the current state of the workflow, stored in a MarkingStore
  55. Workflow configuration framework: workflows: blog_publishing: type: 'workflow' marking_store: type: 'multiple_state'

    arguments: - 'currentPlace' supports: [AppBundle\Entity\BlogPost] places: - draft # ...
  56. Workflow configuration framework: workflows: blog_publishing: type: 'workflow' marking_store: type: 'multiple_state'

    arguments: - 'currentPlace' supports: [AppBundle\Entity\BlogPost] places: - draft # ... transitions: to_review: from: draft to: review # ...
  57. • a definition will be created for each workflow •

    a workflow can be retrieved from the service container (workflow.<name>) • the service is an instance of Workflow Workflow configuration
  58. • can() test if a transition can be applied •

    apply() applies a transition • getEnabledTransitions() returns all applyable transitions The Workflow class
  59. Applying transitions public function publishIfPossible( Article $article, Workflow $workflow )

    { if ($workflow->can($article, 'publish')) { $workflow->apply($article, 'publish'); } }
  60. • several events are triggered throughout the lifecycle of a

    workflow • listeners can access the workflow through the passed event object Workflow events
  61. • workflow.leave before a place is left • workflow.transition before

    a transition is applied • workflow.enter before a place is entered Workflow events
  62. • workflow.entered after a place has been entered • workflow.completed

    after a transition was applied • workflow.announce announces all enabled transitions Workflow events
  63. • transitions can be blocked by listeners of the workflow.guard

    event • an instance of GuardEvent will be passed • guard listeners are taken into account when can() is executed The guard event
  64. The GuardEvent class GuardEvent extends Event { private $blocked =

    false; public function isBlocked() { return $this->blocked; } public function setBlocked($blocked) { $this->blocked = (bool) $blocked; } }
  65. Phone +49 221 16 53 54 0 Email [email protected] SensioLabs

    Training Department training.sensiolabs.com Address Balthasarstraße 79 50670 Köln Germany SensioLabs