Share
Embed
Transcript
106 slides
-
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. -
• LTS release (3 years of support) • Symfony 3.3
+ additional features + additional deprecations • release: November 2017 Symfony 3.4 -
• standard release (8 months of support) • Symfony 3.3
+ additional features - deprecated features • release: November 2017 Symfony 4.0 -
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 -
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 -
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 -
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 -
• Flex prefers composition over inheritance. • New project start
with almost no dependencies. • Only needed features are added by developers. What is Symfony Flex? -
• 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? -
• 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? -
• 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? -
• 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 -
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] -
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] -
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] -
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 -
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 -
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. -
• Groups packages that are useful during development: • logging
(Monolog) • profiling (WebProfilerBundle) • testing (PhpUnitBridge) Example: The debug pack -
• 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 -
• are maintained by the community • can be created
for MIT and Apache licensed packages • are not enabled by default Contrib recipes -
Activating contrib recipes in composer.json { "extra": { "symfony": {
"id": "01BX217DNRHSWETJFT83M3XDE9", "allow-contrib": false } } } -
Activating contrib recipes in composer.json { "extra": { "symfony": {
"id": "01BX217DNRHSWETJFT83M3XDE9", "allow-contrib": false } } } -
Activating contrib recipes in composer.json { "extra": { "symfony": {
"id": "01BX217DNRHSWETJFT83M3XDE9", "allow-contrib": true } } } -
• 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 -
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. -
• 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 -
• collects PHP classes based on glob patterns and PSR-4-compatible
namespaces • some files/directories can be excluded PSR-4 based service configuration -
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' -
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. -
Usage of environment variables # defining default values for env
var placeholders parameters: env(DB): 'sqlite://../../var/data.db' doctrine: dbal: url: '%env(DB)%' -
• 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 -
• „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 -
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)%' -
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 -
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 -
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 -
• encapsulates the data that should be cached • associates
data with a key and expiration time • CacheItemInterface is specified by PSR-6 Cache items -
• 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 -
• 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 -
• APCu • Doctrine • Filesystem • Memcached • Pdo
• Redis Built-in adapters -
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 -
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 -
CacheItemInterface interface CacheItemInterface { public function getKey(); public function get();
public function isHit(); public function set($value); public function expiresAt($expiration); public function expiresAfter($time); } -
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(); } -
Storing cache items public function computeAndCache(CacheItemPoolInterface $cache) { $item =
$cache->getItem('cache_key'); // compute some $value $item->set($value); $cache->save($item); } -
Retrieve cache items public function retrieveFromCache(CacheItemPoolInterface $cache): ?Value { $item
= $cache->getItem('cache_key'); if ($item->isHit()) { return $item->get(); } return null; } -
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; } -
Custom cache pools framework: cache: pools: # the "api" cache
pool will be # available as the cache.api service api: adapter: memcached -
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 -
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); } -
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; } -
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. -
Terms 1/1 • Place the states a workflow can be
in • Transition an action that brings the workflow from one place into another -
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 -
Workflow configuration framework: workflows: blog_publishing: type: 'workflow' marking_store: type: 'multiple_state'
# or 'single_state' arguments: - 'currentPlace' # ... -
Workflow configuration framework: workflows: blog_publishing: type: 'workflow' marking_store: type: 'multiple_state'
arguments: - 'currentPlace' supports: [AppBundle\Entity\BlogPost] # ... -
Workflow configuration framework: workflows: blog_publishing: type: 'workflow' marking_store: type: 'multiple_state'
arguments: - 'currentPlace' supports: [AppBundle\Entity\BlogPost] places: - draft # ... -
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 # ... -
• 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 -
• can() test if a transition can be applied •
apply() applies a transition • getEnabledTransitions() returns all applyable transitions The Workflow class -
Applying transitions public function publishIfPossible( Article $article, Workflow $workflow )
{ if ($workflow->can($article, 'publish')) { $workflow->apply($article, 'publish'); } } -
• several events are triggered throughout the lifecycle of a
workflow • listeners can access the workflow through the passed event object Workflow events -
• workflow.leave before a place is left • workflow.transition before
a transition is applied • workflow.enter before a place is entered Workflow events -
• workflow.entered after a place has been entered • workflow.completed
after a transition was applied • workflow.announce announces all enabled transitions Workflow events -
• 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 -
The GuardEvent class GuardEvent extends Event { private $blocked =
false; public function isBlocked() { return $this->blocked; } public function setBlocked($blocked) { $this->blocked = (bool) $blocked; } } -
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