Slide 1

Slide 1 text

Symfony4 Deep Dive SensioLabs

Slide 2

Slide 2 text

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.

Slide 3

Slide 3 text

• SSID: GT Conference • Username: SymfonyLive • Password: Berlin2017 Wifi

Slide 4

Slide 4 text

SensioLabs Introduction

Slide 5

Slide 5 text

The Symfony Release Cycle

Slide 6

Slide 6 text

We are here

Slide 7

Slide 7 text

• LTS release (3 years of support) • Symfony 3.3 + additional features + additional deprecations • release: November 2017 Symfony 3.4

Slide 8

Slide 8 text

• standard release (8 months of support) • Symfony 3.3 + additional features - deprecated features • release: November 2017 Symfony 4.0

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

The Symfony Standard Edition

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

Symfony Flex

Slide 15

Slide 15 text

• Flex prefers composition over inheritance. • New project start with almost no dependencies. • Only needed features are added by developers. What is Symfony Flex?

Slide 16

Slide 16 text

• 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?

Slide 17

Slide 17 text

Bootstrapping a Symfony application

Slide 18

Slide 18 text

Using Composer composer create-project \ symfony/framework- standard-edition:3.3.* \ my-app

Slide 19

Slide 19 text

Using the Symfony Installer symfony new my-app 3.3

Slide 20

Slide 20 text

Bootstrapping an application using Flex composer create-project \ symfony/skeleton my-app

Slide 21

Slide 21 text

Initial project size in comparison Symfony 3 Symfony 4

Slide 22

Slide 22 text

Symfony 3 Symfony 4 Basic directory structure in comparison

Slide 23

Slide 23 text

Hands on: User Group Radar

Slide 24

Slide 24 text

Initialize the project composer create-project \ symfony/skeleton:^3.4@beta \ meetup

Slide 25

Slide 25 text

https://goo.gl/PVGrzA Download example code

Slide 26

Slide 26 text

Recipes

Slide 27

Slide 27 text

• 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?

Slide 28

Slide 28 text

• 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?

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

• 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

Slide 31

Slide 31 text

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]

Slide 32

Slide 32 text

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]

Slide 33

Slide 33 text

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]

Slide 34

Slide 34 text

Aliases

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Packs

Slide 38

Slide 38 text

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.

Slide 39

Slide 39 text

• Groups packages that are useful during development: • logging (Monolog) • profiling (WebProfilerBundle) • testing (PhpUnitBridge) Example: The debug pack

Slide 40

Slide 40 text

• symfony/monolog-bundle • easycorp/easy-log-handler • symfony/profiler-pack • symfony/phpunit-bridge • symfony/var-dumper Example: The debug pack

Slide 41

Slide 41 text

• debug-pack • profiler-pack • orm-pack • webpack-encore-pack • api-pack Popular packs

Slide 42

Slide 42 text

Contrib recipes

Slide 43

Slide 43 text

• 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

Slide 44

Slide 44 text

• are maintained by the community • can be created for MIT and Apache licensed packages • are not enabled by default Contrib recipes

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Interactive activation

Slide 49

Slide 49 text

SensioLabs

Slide 50

Slide 50 text

SensioLabs Improved Dependency Injection

Slide 51

Slide 51 text

• 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

Slide 52

Slide 52 text

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.

Slide 53

Slide 53 text

• 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

Slide 54

Slide 54 text

• collects PHP classes based on glob patterns and PSR-4-compatible namespaces • some files/directories can be excluded PSR-4 based service configuration

Slide 55

Slide 55 text

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'

Slide 56

Slide 56 text

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.

Slide 57

Slide 57 text

Usage of environment variables # defining default values for env var placeholders parameters: env(DB): 'sqlite://../../var/data.db' doctrine: dbal: url: '%env(DB)%'

Slide 58

Slide 58 text

• 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

Slide 59

Slide 59 text

• „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

Slide 60

Slide 60 text

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)%'

Slide 61

Slide 61 text

SensioLabs

Slide 62

Slide 62 text

SensioLabs The Cache Component

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

PSR-6

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

• encapsulates the data that should be cached • associates data with a key and expiration time • CacheItemInterface is specified by PSR-6 Cache items

Slide 68

Slide 68 text

• 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

Slide 69

Slide 69 text

• 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

Slide 70

Slide 70 text

• APCu • Doctrine • Filesystem • Memcached • Pdo • Redis Built-in adapters

Slide 71

Slide 71 text

Configuring the default adapter framework: cache: app: cache.adapter.redis system: cache.adapter.apcu

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

CacheItemInterface interface CacheItemInterface { public function getKey(); public function get(); public function isHit(); public function set($value); public function expiresAt($expiration); public function expiresAfter($time); }

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

Storing cache items public function computeAndCache(CacheItemPoolInterface $cache) { $item = $cache->getItem('cache_key'); // compute some $value $item->set($value); $cache->save($item); }

Slide 77

Slide 77 text

Retrieve cache items public function retrieveFromCache(CacheItemPoolInterface $cache): ?Value { $item = $cache->getItem('cache_key'); if ($item->isHit()) { return $item->get(); } return null; }

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

Custom cache pools framework: cache: pools: # the "api" cache pool will be # available as the cache.api service api: adapter: memcached

Slide 80

Slide 80 text

PSR-16

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

Wrapping a PSR-6 adapter services: api_cache: class: Symfony\Component\Cache\Simple\Psr6Cache arguments: - '@cache.app'

Slide 85

Slide 85 text

SensioLabs

Slide 86

Slide 86 text

SensioLabs The Workflow Component

Slide 87

Slide 87 text

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.

Slide 88

Slide 88 text

Terms 1/1 • Place the states a workflow can be in • Transition an action that brings the workflow from one place into another

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

Workflow configuration framework: workflows: blog_publishing: type: 'workflow’ # or ‘state_machine’ # ...

Slide 91

Slide 91 text

Workflow configuration framework: workflows: blog_publishing: type: 'workflow' marking_store: type: 'multiple_state' # or 'single_state' arguments: - 'currentPlace' # ...

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

• a definition will be created for each workflow • a workflow can be retrieved from the service container (workflow.) • the service is an instance of Workflow Workflow configuration

Slide 96

Slide 96 text

• can() test if a transition can be applied • apply() applies a transition • getEnabledTransitions() returns all applyable transitions The Workflow class

Slide 97

Slide 97 text

Applying transitions public function publishIfPossible( Article $article, Workflow $workflow ) { if ($workflow->can($article, 'publish')) { $workflow->apply($article, 'publish'); } }

Slide 98

Slide 98 text

• several events are triggered throughout the lifecycle of a workflow • listeners can access the workflow through the passed event object Workflow events

Slide 99

Slide 99 text

• workflow.leave before a place is left • workflow.transition before a transition is applied • workflow.enter before a place is entered Workflow events

Slide 100

Slide 100 text

• workflow.entered after a place has been entered • workflow.completed after a transition was applied • workflow.announce announces all enabled transitions Workflow events

Slide 101

Slide 101 text

• 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

Slide 102

Slide 102 text

The GuardEvent class GuardEvent extends Event { private $blocked = false; public function isBlocked() { return $this->blocked; } public function setBlocked($blocked) { $this->blocked = (bool) $blocked; } }

Slide 103

Slide 103 text

SensioLabs

Slide 104

Slide 104 text

Please leave feedback https://joind.in/talk/0bb53

Slide 105

Slide 105 text

Full code example https://github.com/sensiolabs-de/flex-meetup

Slide 106

Slide 106 text

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