Symfony Components 4.0
Symfony Components 4.0
Symfony Components 4.0
Version: 4.0
generated on January 18, 2018
The Components Book (4.0)
This work is licensed under the “Attribution-Share Alike 3.0 Unported” license (http://creativecommons.org/
licenses/by-sa/3.0/).
You are free to share (to copy, distribute and transmit the work), and to remix (to adapt the work) under the
following conditions:
• Attribution: You must attribute the work in the manner specified by the author or licensor (but not in
any way that suggests that they endorse you or your use of the work).
• Share Alike: If you alter, transform, or build upon this work, you may distribute the resulting work only
under the same, similar or a compatible license. For any reuse or distribution, you must make clear to
others the license terms of this work.
The information in this book is distributed on an “as is” basis, without warranty. Although every precaution
has been taken in the preparation of this work, neither the author(s) 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.
If you find typos or errors, feel free to report them by creating a ticket on the Symfony ticketing system
(http://github.com/symfony/symfony-docs/issues). Based on tickets and users feedback, this book is
continuously updated.
Contents at a Glance
If you're starting a new project (or already have a project) that will use one or more components, the
easiest way to integrate everything is with Composer1. Composer is smart enough to download the
component(s) that you need and take care of autoloading so that you can begin using the libraries
immediately.
This article will take you through using The Finder Component, though this applies to using any
component.
The name symfony/finder is written at the top of the documentation for whatever component you
want.
Install composer2 if you don't have it already present on your system. Depending on how you install,
you may end up with a composer.phar file in your directory. In that case, no worries! Just run
php composer.phar require symfony/finder.
1. https://getcomposer.org
2. https://getcomposer.org/download/
PDF brought to you by Chapter 1: How to Install and Use the Symfony Components | 4
Now what?
Now that the component is installed and autoloaded, read the specific component's documentation to
find out more about how to use it.
And have fun!
PDF brought to you by Chapter 1: How to Install and Use the Symfony Components | 5
The Asset component manages URL generation and versioning of web assets such as CSS
stylesheets, JavaScript files and image files.
In the past, it was common for web applications to hardcode URLs of web assets. For example:
This practice is no longer recommended unless the web application is extremely simple. Hardcoding
URLs can be a disadvantage because:
• Templates get verbose: you have to write the full path for each asset. When using the Asset
component, you can group assets in packages to avoid repeating the common part of their path;
• Versioning is difficult: it has to be custom managed for each application. Adding a version (e.g.
main.css?v=5) to the asset URLs is essential for some applications because it allows you to control how
the assets are cached. The Asset component allows you to define different versioning strategies for
each package;
• Moving assets location is cumbersome and error-prone: it requires you to carefully update the
URLs of all assets included in all templates. The Asset component allows to move assets effortlessly
just by changing the base path value associated with the package of assets;
• It's nearly impossible to use multiple CDNs: this technique requires you to change the URL of
the asset randomly for each request. The Asset component provides out-of-the-box support for any
number of multiple CDNs, both regular (http://) and secure (https://).
Installation
You can install the component in two different ways:
Usage
Asset Packages
The Asset component manages assets through packages. A package groups all the assets which share
the same properties: versioning strategy, base path, CDN hosts, etc. In the following basic example, a
package is created to manage assets without any versioning:
getUrl()4
Returns an absolute or root-relative public path.
Versioned Assets
One of the main features of the Asset component is the ability to manage the versioning of the
application's assets. Asset versions are commonly used to control how these assets are cached.
Instead of relying on a simple version mechanism, the Asset component allows you to define advanced
versioning strategies via PHP classes. The two built-in strategies are the EmptyVersionStrategy5,
which doesn't add any version to the asset and StaticVersionStrategy6, which allows you to set
the version with a format string.
In this example, the StaticVersionStrategy is used to append the v1 suffix to any asset path:
1. https://packagist.org/packages/symfony/asset
2. http://api.symfony.com/4.0/Symfony/Component/Asset/PackageInterface.html
3. http://api.symfony.com/4.0/Symfony/Component/Asset/PackageInterface.html#method_getVersion
4. http://api.symfony.com/4.0/Symfony/Component/Asset/PackageInterface.html#method_getUrl
5. http://api.symfony.com/4.0/Symfony/Component/Asset/VersionStrategy/EmptyVersionStrategy.html
6. http://api.symfony.com/4.0/Symfony/Component/Asset/VersionStrategy/StaticVersionStrategy.html
In case you want to modify the version format, pass a sprintf-compatible format string as the second
argument of the StaticVersionStrategy constructor:
Listing 2-4 1 // put the 'version' word before the version value
2 $package = new Package(new StaticVersionStrategy('v1', '%s?version=%s'));
3
4 echo $package->getUrl('/image.png');
5 // result: /image.png?version=v1
6
7 // put the asset version before its path
8 $package = new Package(new StaticVersionStrategy('v1', '%2$s/%1$s'));
9
10 echo $package->getUrl('/image.png');
11 // result: /v1/image.png
12
13 echo $package->getUrl('image.png');
14 // result: v1/image.png
Grouped Assets
Often, many assets live under a common path (e.g. /static/images). If that's your case, replace the
default Package8 class with PathPackage9 to avoid repeating that path over and over again:
Listing 2-6
7. http://api.symfony.com/4.0/Symfony/Component/Asset/VersionStrategy/VersionStrategyInterface.html
8. http://api.symfony.com/4.0/Symfony/Component/Asset/Package.html
9. http://api.symfony.com/4.0/Symfony/Component/Asset/PathPackage.html
Now that the request context is set, the PathPackage will prepend the current request base URL.
So, for example, if your entire site is hosted under the /somewhere directory of your web server
root directory and the configured base path is /static/images, all paths will be prefixed with
/somewhere/static/images.
10. http://api.symfony.com/4.0/Symfony/Component/Asset/UrlPackage.html
This is useful because assets will automatically be requested via HTTPS if a visitor is viewing your site in
https. Just make sure that your CDN host supports https.
In case you serve assets from more than one domain to improve application performance, pass an array
of URLs as the first argument to the UrlPackage constructor:
For each asset, one of the URLs will be randomly used. But, the selection is deterministic, meaning that
each asset will be always served by the same domain. This behavior simplifies the management of HTTP
cache.
Named Packages
Applications that manage lots of different assets may need to group them in packages with the same
versioning strategy and base path. The Asset component includes a Packages11 class to simplify
management of several packages.
In the following example, all packages use the same versioning strategy, but they all have different base
paths:
11. http://api.symfony.com/4.0/Symfony/Component/Asset/Packages.html
The Packages class allows to define a default package, which will be applied to assets that don't define
the name of package to use. In addition, this application defines a package named img to serve images
from an external domain and a doc package to avoid repeating long paths when linking to a document
inside a template:
Learn more
The BrowserKit component simulates the behavior of a web browser, allowing you to make requests,
click on links and submit forms programmatically.
The BrowserKit component can only make internal requests to your application. If you need to make
requests to external sites and applications, consider using Goutte1, a simple web scraper based on
Symfony Components.
Installation
You can install the component in two different ways:
Basic Usage
Creating a Client
The component only provides an abstract client and does not provide any backend ready to use for the
HTTP layer.
To create your own client, you must extend the abstract Client class and implement the
doRequest()3 method. This method accepts a request and should return a response:
Listing 3-1
1. https://github.com/FriendsOfPHP/Goutte
2. https://packagist.org/packages/symfony/browser-kit
3. http://api.symfony.com/4.0/Symfony/Component/BrowserKit/Client.html#method_doRequest
For a simple implementation of a browser based on the HTTP layer, have a look at Goutte4. For
an implementation based on HttpKernelInterface, have a look at the Client5 provided by the
HttpKernel component.
Making Requests
Use the request()6 method to make HTTP requests. The first two arguments are the HTTP method
and the requested URL:
Listing 3-2
use Acme\Client;
The value returned by the request() method is an instance of the Crawler7 class, provided by the
DomCrawler component, which allows accessing and traversing HTML elements programmatically.
Clicking Links
The Crawler object is capable of simulating link clicks. First, pass the text content of the link to the
selectLink() method, which returns a Link object. Then, pass this object to the click() method,
which performs the needed HTTP GET request to simulate the link click:
Submitting Forms
The Crawler object is also capable of selecting forms. First, select any of the form's buttons with the
selectButton() method. Then, use the form() method to select the form which the button belongs
to.
After selecting the form, fill in its data and send it using the submit() method (which makes the needed
HTTP POST request to submit the form contents):
4. https://github.com/FriendsOfPHP/Goutte
5. http://api.symfony.com/4.0/Symfony/Component/HttpKernel/Client.html
6. http://api.symfony.com/4.0/Symfony/Component/BrowserKit/Client.html#method_request
7. http://api.symfony.com/4.0/Symfony/Component/DomCrawler/Crawler.html
Cookies
Retrieving Cookies
The Client implementation exposes cookies (if any) through a CookieJar8, which allows you to store
and retrieve any cookie while making requests with the client:
8. http://api.symfony.com/4.0/Symfony/Component/BrowserKit/CookieJar.html
Setting Cookies
You can also create cookies and add them to a cookie jar that can be injected into the client constructor:
History
The client stores all your requests allowing you to go back and forward in your history:
You can delete the client's history with the restart() method. This will also delete all the cookies:
The Cache component provides an extended PSR-61 implementation as well as a PSR-162 "Simple
Cache" implementation for adding cache to your applications. It is designed to have a low overhead
and it ships with ready to use adapters for the most common caching backends.
Installation
You can install the component in 2 different ways:
Both methods support the same cache adapters and will give you very similar performance.
The component also contains adapters to convert between PSR-6 and PSR-16 caches. See Adapters
For Interoperability between PSR-6 and PSR-16 Cache.
1. http://www.php-fig.org/psr/psr-6/
2. http://www.php-fig.org/psr/psr-16/
3. https://packagist.org/packages/symfony/cache
Listing 4-1
use Symfony\Component\Cache\Simple\FilesystemCache;
Now you can create, retrieve, update and delete items using this object:
To find out more about each of these classes, you can read the PSR-6 Cache Pool page. These
"Simple" (PSR-16) cache classes aren't identical to the PSR-6 Adapters on that page, but each share
constructor arguments and use-cases.
• ApcuCache6
4. http://www.php-fig.org/psr/psr-16/
5. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/FilesystemCache.html
Pool
A logical repository of cache items. All cache operations (saving items, looking for items, etc.) are
performed through the pool. Applications can define as many pools as needed.
Adapter
It implements the actual caching mechanism to store the information in the filesystem, in a
database, etc. The component provides several ready to use adapters for common caching backends
(Redis, APCu, Doctrine, PDO, etc.)
Listing 4-4
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
Now you can create, retrieve, update and delete items using this cache pool:
Listing 4-5 1 // create a new item by trying to get it from the cache
2 $numProducts = $cache->getItem('stats.num_products');
3
4 // assign a value to the item and save it
6. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/ApcuCache.html
7. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/ArrayCache.html
8. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/ChainCache.html
9. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/DoctrineCache.html
10. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/FilesystemCache.html
11. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/MemcachedCache.html
12. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/NullCache.html
13. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/PdoCache.html
14. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/PhpArrayCache.html
15. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/PhpFilesCache.html
16. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/RedisCache.html
17. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/TraceableCache.html
18. http://www.php-fig.org/psr/psr-6/
19. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/FilesystemAdapter.html
For a list of all of the supported adapters, see Cache Pools and Supported Adapters.
Cache invalidation is the process of removing all cached items related to a change in the state of your
model. The most basic kind of invalidation is direct items deletion. But when the state of a primary
resource has spread across several cached items, keeping them in sync can be difficult.
The Symfony Cache component provides two mechanisms to help solving this problem:
If $cache implements TagAwareAdapterInterface2, you can invalidate the cached items by calling
invalidateTags()3:
Listing 5-2 1 // invalidate all items related to `tag_1` or `tag_3`
2 $cache->invalidateTags(array('tag_1', 'tag_3'));
3
1. http://api.symfony.com/4.0/Symfony/Component/Cache/CacheItem.html#method_tag
2. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/TagAwareAdapterInterface.html
3. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/TagAwareAdapterInterface.html#method_invalidateTags
Using tags invalidation is very useful when tracking cache keys becomes difficult.
4. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/TagAwareAdapter.html
5. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/TagAwareAdapterInterface.html
6. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/TagAwareAdapterInterface.html#method_invalidateTags
7. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/TagAwareAdapter.html
Cache items are the information units stored in the cache as a key/value pair. In the Cache component
they are represented by the CacheItem1 class.
Listing 6-1
// $cache pool object was created before
$numProducts = $cache->getItem('stats.num_products');
Then, use the set()2 method to set the data stored in the cache item:
1. http://api.symfony.com/4.0/Symfony/Component/Cache/CacheItem.html
2. http://api.symfony.com/4.0/Psr/Cache/CacheItemInterface.html#method_set
The key and the value of any given cache item can be obtained with the corresponding getter methods:
Listing 6-3
$cacheItem = $cache->getItem('exchange_rate');
// ...
$key = $cacheItem->getKey();
$value = $cacheItem->get();
Cache items define another related method called expiresAt() to set the exact date and time when the
item will expire:
Listing 6-5
$mostPopularNews = $cache->getItem('popular_news');
$mostPopularNews->expiresAt(new \DateTime('tomorrow'));
• Cache Hits occur when the requested item is found in the cache, its value is not corrupted or invalid
and it hasn't expired;
• Cache Misses are the opposite of hits, so they occur when the item is not found in the cache, its
value is corrupted or invalid for any reason or the item has expired.
Cache item objects define a boolean isHit() method which returns true for cache hits:
Cache Pools are the logical repositories of cache items. They perform all the common operations on
items, such as saving them or looking for them. Cache pools are independent from the actual cache
implementation. Therefore, applications can keep using the same cache pool even if the underlying cache
mechanism changes from a file system based cache to a Redis or database based cache.
1. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/AdapterInterface.html
Again, if any of the keys doesn't represent a valid cache item, you won't get a null value but an empty
CacheItem object.
The last method related to fetching cache items is hasItem($key), which returns true if there is a
cache item identified by the given key:
Listing 7-3
// ...
$hasBadges = $cache->hasItem('user_'.$userId.'_badges');
Listing 7-4
// ...
$userFriends = $cache->getItem('user_'.$userId.'_friends');
$userFriends->set($user->getFriends());
$isSaved = $cache->save($userFriends);
Sometimes you may prefer to not save the objects immediately in order to increase the application
performance. In those cases, use the saveDeferred()4 method to mark cache items as "ready to be
persisted" and then call to commit()5 method when you are ready to persist them all:
The saveDeferred() method returns true when the cache item has been successfully added to the
"persist queue" and false otherwise. The commit() method returns true when all the pending items
are successfully saved or false otherwise.
2. http://api.symfony.com/4.0/Symfony/Component/Cache/CacheItem.html
3. http://api.symfony.com/4.0/Psr/Cache/CacheItemPoolInterface.html#method_save
4. http://api.symfony.com/4.0/Psr/Cache/CacheItemPoolInterface.html#method_saveDeferred
5. http://api.symfony.com/4.0/Psr/Cache/CacheItemPoolInterface.html#method_commit
6. http://api.symfony.com/4.0/Psr/Cache/CacheItemPoolInterface.html#method_deleteItem
Use the deleteItems()7 method to delete several cache items simultaneously (it returns true only if
all the items have been deleted, even when any or some of them don't exist):
Listing 7-7
// ...
$areDeleted = $cache->deleteItems(array('category1', 'category2'));
Finally, to remove all the cache items stored in the pool, use the clear()8 method (which returns true
when all items are successfully deleted):
Listing 7-8
// ...
$cacheIsEmpty = $cache->clear();
If the Cache component is used inside a Symfony application, you can remove all the items of a given
cache pool with the following command:
7. http://api.symfony.com/4.0/Psr/Cache/CacheItemPoolInterface.html#method_deleteItems
8. http://api.symfony.com/4.0/Psr/Cache/CacheItemPoolInterface.html#method_clear
This adapter is a high-performance, shared memory cache. It can increase the application performance
very significantly because the cache contents are stored in the shared memory of your server, a
component that is much faster than others, such as the filesystem.
Requirement: The APCu extension1 must be installed and active to use this adapter.
This adapter can be provided an optional namespace string as its first parameter, a default cache lifetime
as its second parameter, and a version string as its third parameter:
It is not recommended to use this adapter when performing a large number of write and delete
operations, as these operations result in fragmentation of the APCu memory, resulting in significantly
degraded performance.
1. https://pecl.php.net/package/APCu
Generally, this adapter is useful for testing purposes, as its contents are stored in memory and not
persisted outside the running PHP process in any way. It can also be useful while warming up caches,
due to the getValues()1 method.
This adapter can be passed a default cache lifetime as its first parameter, and a boolean that toggles
serialization as its second parameter:
1. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/ArrayAdapter.html#method_getValues
This adapter allows to combine any number of the other available cache adapters. Cache items are
fetched from the first adapter which contains them and cache items are saved in all the given adapters.
This offers a simple way of creating a layered cache.
This adapter expects an array of adapters as its first parameter, and optionally a maximum cache lifetime
as its second parameter:
When an item is not found in the first adapter but is found in the next ones, this adapter ensures that
the fetched item is saved in all the adapters where it was previously missing.
The following example shows how to create a chain adapter instance using the fastest and slowest storage
engines, ApcuAdapter1 and FilesystemAdapter2, respectfully:
1. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/ApcuAdapter.html
2. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/FilesystemAdapter.html
This adapter wraps any class extending the Doctrine Cache1 abstract provider, allowing you to use these
providers in your application as if they were Symfony Cache adapters.
This adapter expects a \Doctrine\Common\Cache\CacheProvider instance as its first parameter,
and optionally a namespace and default cache lifetime as its second and third parameters:
1. https://github.com/doctrine/cache
This adapter is useful when you want to improve the application performance but can't install tools like
APCu or Redis on the server. This adapter stores the contents as regular files in a set of directories on the
local file system.
This adapter can optionally be provided a namespace, default cache lifetime, and directory path, as its
first, second, and third parameters:
This adapter is generally the slowest due to the overhead of file IO. If throughput is paramount,
the in-memory adapters (such as APCu, Memcached, and Redis) or the database adapters (such as
Doctrine and PDO & Doctrine) are recommended.
This adapter stores the values in-memory using one (or more) Memcached server1 instances. Unlike the
APCu adapter, and similarly to the Redis adapter, it is not limited to the current server's shared memory;
you can store contents independent of your PHP environment. The ability to utilize a cluster of servers to
provide redundancy and/or fail-over is also available.
Requirements: The Memcached PHP extension2 as well as a Memcached server3 must be installed,
active, and running to use this adapter. Version 2.2 or greater of the Memcached PHP extension4 is
required for this adapter.
This adapter expects a Memcached5 instance to be passed as the first parameter. A namespace and default
cache lifetime can optionally be passed as the second and third parameters:
1. https://memcached.org/
2. http://php.net/manual/en/book.memcached.php
3. https://memcached.org/
4. http://php.net/manual/en/book.memcached.php
5. http://php.net/manual/en/class.memcached.php
The Data Source Name (DSN)9 for this adapter must use the following format:
The DSN must include a IP/host (and an optional port) or a socket path, an optional username and
password (for SASL authentication; it requires that the memcached extension was compiled with --
enable-memcached-sasl) and an optional weight (for prioritizing servers in a cluster; its value is an
integer between 0 and 100 which defaults to null; a higher value means more priority).
Below are common examples of valid DSNs showing a combination of available values:
6. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/MemcachedAdapter.html#method_createConnection
7. http://php.net/manual/en/class.memcached.php
8. https://en.wikipedia.org/wiki/Data_source_name
9. https://en.wikipedia.org/wiki/Data_source_name
10. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/MemcachedAdapter.html#method_createConnection
Available Options
auto_eject_hosts (type: bool,
default: false)
Enables or disables a constant, automatic, re-balancing of the cluster by auto-ejecting hosts that
have exceeded the configured server_failure_limit.
Specifies the compression method used on value payloads. when the compression option is
enabled.
Valid option values include fastlz and zlib, with a default value that varies based on flags used
at compilation.
Specified the maximum buffer size (in bytes) in the context of incoming (receive) socket connection
data.
Valid option values include any positive integer, with a default value that varies by platform and
kernel configuration.
Specified the maximum buffer size (in bytes) in the context of outgoing (send) socket connection
data.
Valid option values include any positive integer, with a default value that varies by platform and
kernel configuration.
Not all library operations are tested in this mode. Mixed TCP and UDP servers are not allowed.
11. https://en.wikipedia.org/wiki/Keepalive
12. https://en.wikipedia.org/wiki/Transmission_Control_Protocol
13. https://en.wikipedia.org/wiki/TCP_NODELAY
14. https://en.wikipedia.org/wiki/Transmission_Control_Protocol
15. https://en.wikipedia.org/wiki/User_Datagram_Protocol
16. https://en.wikipedia.org/wiki/Transmission_Control_Protocol
17. http://php.net/manual/en/class.memcached.php
This adapter stores the cache items in an SQL database. It requires a PDO1, Doctrine DBAL Connection2,
or Data Source Name (DSN)3 as its first parameter, and optionally a namespace, default cache lifetime,
and options array as its second, third, and forth parameters:
When passed a Data Source Name (DSN)4 string (instead of a database connection class instance),
the connection will be lazy-loaded when needed.
1. http://php.net/manual/en/class.pdo.php
2. https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Connection.php
3. https://en.wikipedia.org/wiki/Data_source_name
4. https://en.wikipedia.org/wiki/Data_source_name
PDF brought to you by Chapter 14: PDO & Doctrine DBAL Cache Adapter | 41
This adapter is a highly performant way to cache static data (e.g. application configuration) that is
optimized and preloaded into OPcache memory storage:
This adapter requires PHP 7.x and should be used with the php.ini setting opcache.enable on.
This adapter wraps a PSR-61 compliant cache item pool interface2. It is used to integrate your application's
cache item pool implementation with the Symfony Cache Component by consuming any implementation
of Psr\Cache\CacheItemPoolInterface.
This adapter expects a Psr\Cache\CacheItemPoolInterface instance as its first parameter, and
optionally a namespace and default cache lifetime as its second and third parameters:
1. http://www.php-fig.org/psr/psr-6/
2. http://www.php-fig.org/psr/psr-6/#cacheitempoolinterface
This adapter stores the values in-memory using one (or more) Redis server1 instances. Unlike the APCu
adapter, and similarly to the Memcached adapter, it is not limited to the current server's shared memory;
you can store contents independent of your PHP environment. The ability to utilize a cluster of servers to
provide redundancy and/or fail-over is also available.
Requirements: At least one Redis server2 must be installed and running to use this adapter.
Additionally, this adapter requires a compatible extension or library that implements \Redis,
\RedisArray, RedisCluster, or \Predis.
This adapter expects a Redis3, RedisArray4, RedisCluster5, or Predis6 instance to be passed as the first
parameter. A namespace and default cache lifetime can optionally be passed as the second and third
parameters:
1. https://redis.io/
2. https://redis.io/
3. https://github.com/phpredis/phpredis
4. https://github.com/phpredis/phpredis/blob/master/arrays.markdown#readme
5. https://github.com/phpredis/phpredis/blob/master/cluster.markdown#readme
6. https://packagist.org/packages/predis/predis
The DSN can specify either an IP/host (and an optional port) or a socket path, as well as a user and
password and a database index.
A Data Source Name (DSN)9 for this adapter must use the following format.
Below are common examples of valid DSNs showing a combination of available values:
7. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/RedisAdapter.html#method_createConnection
8. https://en.wikipedia.org/wiki/Data_source_name
9. https://en.wikipedia.org/wiki/Data_source_name
10. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/RedisAdapter.html#method_createConnection
Available Options
class (type: string)
Specifies the connection library to return, either \Redis or \Predis\Client. If none is specified, it will
return \Redis if the redis extension is available, and \Predis\Client otherwise.
When using the Predis11 library some additional Predis-specific options are available. Reference the
Predis Connection Parameters12 documentation for more information.
11. https://packagist.org/packages/predis/predis
12. https://github.com/nrk/predis/wiki/Connection-Parameters#list-of-connection-parameters
Sometimes, you may have a Cache object that implements the PSR-16 standard, but need to pass it to
an object that expects a PSR-6 cache adapter. Or, you might have the opposite situation. The cache
component contains two classes for bidirectional interoperability between PSR-6 and PSR-16 caches.
But, you already have a PSR-16 cache object, and you'd like to pass this to the class instead. No problem!
The Cache component provides the SimpleCacheAdapter1 class for exactly this use-case:
1. http://api.symfony.com/4.0/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.html
PDF brought to you by Chapter 18: Adapters For Interoperability between PSR-6 and PSR-16 Cache | 47
But, you already have a PSR-6 cache pool object, and you'd like to pass this to the class instead. No
problem! The Cache component provides the Psr6Cache2 class for exactly this use-case:
2. http://api.symfony.com/4.0/Symfony/Component/Cache/Simple/Psr6Cache.html
PDF brought to you by Chapter 18: Adapters For Interoperability between PSR-6 and PSR-16 Cache | 48
The ClassLoader component was removed in Symfony 4.0. As an alternative, use any of the class
loading optimizations1 provided by Composer.
1. https://getcomposer.org/doc/articles/autoloader-optimization.md
The Config component provides several classes to help you find, load, combine, autofill and validate
configuration values of any kind, whatever their source may be (YAML, XML, INI files, or for
instance a database).
Installation
You can install the component in 2 different ways:
Then, require the vendor/autoload.php file to enable the autoloading mechanism provided by
Composer. Otherwise, your application won't be able to find the classes of this Symfony component.
Learn More
• Caching based on Resources
• Defining and Processing Configuration Values
• Loading Resources
• How to Create Friendly Configuration for a Bundle
• How to Load Service Configuration inside a Bundle
• How to Simplify Configuration of Multiple Bundles
1. https://packagist.org/packages/symfony/config
When all configuration resources are loaded, you may want to process the configuration values and
combine them all in one file. This file acts like a cache. Its contents don’t have to be regenerated every
time the application runs – only when the configuration resources are modified.
For example, the Symfony Routing component allows you to load all routes, and then dump a URL
matcher or a URL generator based on these routes. In this case, when one of the resources is modified
(and you are working in a development environment), the generated file should be invalidated and
regenerated. This can be accomplished by making use of the ConfigCache1 class.
The example below shows you how to collect resources, then generate some code based on the resources
that were loaded and write this code to the cache. The cache also receives the collection of resources that
were used for generating the code. By looking at the "last modified" timestamp of these resources, the
cache can tell if it is still fresh or that its contents should be regenerated:
1. http://api.symfony.com/4.0/Symfony/Component/Config/ConfigCache.html
In debug mode, a .meta file will be created in the same directory as the cache file itself. This .meta file
contains the serialized resources, whose timestamps are used to determine if the cache is still fresh. When
not in debug mode, the cache is considered to be "fresh" as soon as it exists, and therefore no .meta file
will be generated.
When loading multiple configuration files, it should be possible to merge and overwrite some values.
Other values should not be merged and stay as they are when first encountered. Also, some keys are only
available when another key has a specific value (in the sample configuration above: the memory key only
makes sense when the driver is sqlite).
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 53
The root node itself is an array node, and has children, like the boolean node auto_connect and the
scalar node default_connection. In general: after defining a node, a call to end() takes you one
step up in the hierarchy.
Node Type
It is possible to validate the type of a provided value by using the appropriate node definition. Node types
are available for:
• scalar (generic type that includes booleans, strings, integers, floats and null)
• boolean
• integer
• float
• enum (similar to scalar, but it only allows a finite set of values)
• array
• variable (no validation)
1. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/TreeBuilder.html
2. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/TreeBuilder.html
3. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/ConfigurationInterface.html
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 54
Enum Nodes
Enum nodes provide a constraint to match the given input against a set of values:
This will restrict the delivery options to be either standard, expedited or priority.
Array Nodes
It is possible to add a deeper level to the hierarchy, by adding an array node. The array node itself, may
have a pre-defined set of variable nodes:
Or you may define a prototype for each node inside an array node:
4. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.html#method_min
5. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.html#method_max
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 55
A prototype can be used to add a definition which may be repeated many times inside the current node.
According to the prototype definition in the example above, it is possible to have multiple connection
arrays (containing a driver, host, etc.).
Sometimes, to improve the user experience of your application or bundle, you may allow to use a simple
string or numeric value where an array value is required. Use the castToArray() helper to turn those
variables into arrays:
Listing 22-8
->arrayNode('hosts')
->beforeNormalization()->castToArray()->end()
// ...
->end()
requiresAtLeastOneElement()
There should be at least one element in the array (works only when isRequired() is also called).
addDefaultsIfNotSet()
If any child nodes have default values, use them if explicit values haven't been provided.
normalizeKeys(false)
If called (with false), keys with dashes are not normalized to underscores. It is recommended to
use this with prototype nodes where the user will define a key-value map, to avoid an unnecessary
transformation.
ignoreExtraKeys()
Allows extra config keys to be specified under an array without throwing an exception.
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 56
Listing 22-12
Array(
[0] => 'mysql'
[1] => 'sqlite'
)
The previous output matches the expected result. However, given the configuration tree, when using the
following YAML configuration:
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 57
As of writing this, there is an inconsistency: if only one file provides the configuration in question,
the keys (i.e. sf_connection and default) are not lost. But if more than one file provides the
configuration, the keys are lost as described above.
The argument of this method (name in the example above) defines the name of the attribute added to
each XML node to differentiate them. Now you can use the same YAML configuration shown before or
the following XML configuration:
In both cases, the processed configuration maintains the sf_connection and default keys:
isRequired()
Must be defined (but may be empty)
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 58
default*()
(null, true, false), shortcut for defaultValue()
treat*Like()
(null, true, false), provide a replacement value in case the value is *.
If you use the Web Debug Toolbar, these deprecation notices are shown when the configuration is
rebuilt.
6. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/NodeDefinition.html#method_setDeprecated
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 59
The info will be printed as a comment when dumping the configuration tree with the config:dump-
reference command.
In YAML you may have:
Listing 22-24 1 # This value is only used for the search results page.
2 entries_per_page: 25
and in XML:
Listing 22-25 1 <!-- entries-per-page: This value is only used for the search results page. -->
2 <config entries-per-page="25" />
Optional Sections
If you have entire sections which are optional and can be enabled/disabled, you can take advantage of
the shortcut canBeEnabled()8 and canBeDisabled()9 methods:
The canBeDisabled() method looks about the same except that the section would be enabled by
default.
Merging Options
Extra options concerning the merge process may be provided. For arrays:
7. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/NodeDefinition.html#method_info
8. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.html#method_canBeEnabled
9. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.html#method_canBeDisabled
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 60
Appending Sections
If you have a complex configuration to validate then the tree can grow to be large and you may want to
split it up into sections. You can do this by making a section a separate node and then appending it into
the main tree with append():
This is also useful to help you avoid repeating yourself if you have sections of the config that are repeated
in different places.
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 61
Normalization
When the config files are processed they are first normalized, then merged and finally the tree is used
to validate the resulting array. The normalization process is used to remove some of the differences that
result from different configuration formats, mainly the differences between YAML and XML.
The separator used in keys is typically _ in YAML and - in XML. For example, auto_connect in YAML
and auto-connect in XML. The normalization would make both of these auto_connect.
The target key will not be altered if it's mixed like foo-bar_moo or if it already exists.
Another difference between YAML and XML is in the way arrays of values may be represented. In YAML
you may have:
and in XML:
This difference can be removed in normalization by pluralizing the key used in XML. You can specify
that you want a key to be pluralized in this way with fixXmlConfig():
If it is an irregular pluralization you can specify the plural to use as a second argument:
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 62
As well as fixing this, fixXmlConfig() ensures that single XML elements are still turned into an array.
So you may have:
By default connection would be an array in the first case and a string in the second making it difficult
to validate. You can ensure it is always an array with fixXmlConfig().
You can further control the normalization process if you need to. For example, you may want to allow a
string to be set and used as a particular key or several keys to be set explicitly. So that, if everything apart
from name is optional in this config:
By changing a string value into an associative array with name as the key:
Validation Rules
More advanced validation rules can be provided using the ExprBuilder10. This builder implements a
fluent interface for a well-known control structure. The builder is used for adding advanced validation
rules to node definitions, like:
Listing 22-38
10. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/ExprBuilder.html
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 63
A validation rule always has an "if" part. You can specify this part in the following ways:
• ifTrue()
• ifString()
• ifNull()
• ifEmpty() (since Symfony 3.2)
• ifArray()
• ifInArray()
• ifNotInArray()
• always()
• then()
• thenEmptyArray()
• thenInvalid()
• thenUnset()
Usually, "then" is a closure. Its return value will be used as a new value for the node, instead of the node's
original value.
11. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Processor.html
12. http://api.symfony.com/4.0/Symfony/Component/Config/Definition/Builder/TreeBuilder.html
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 64
PDF brought to you by Chapter 22: Defining and Processing Configuration Values | 65
The IniFileLoader parses the file contents using the parse_ini_file1 function. Therefore,
you can only set parameters to string values. To set parameters to other data types (e.g. boolean,
integer, etc), the other loaders are recommended.
Locating Resources
Loading the configuration normally starts with a search for resources, mostly files. This can be done with
the FileLocator2:
The locator receives a collection of locations where it should look for files. The first argument of
locate() is the name of the file to look for. The second argument may be the current path and when
supplied, the locator will look in this directory first. The third argument indicates whether or not the
locator should return the first file it has found or an array containing all matches.
Resource Loaders
For each type of resource (YAML, XML, annotation, etc.) a loader must be defined. Each loader should
implement LoaderInterface3 or extend the abstract FileLoader4 class, which allows for recursively
importing other resources:
1. http://php.net/manual/en/function.parse-ini-file.php
2. http://api.symfony.com/4.0/Symfony/Component/Config/FileLocator.html
3. http://api.symfony.com/4.0/Symfony/Component/Config/Loader/LoaderInterface.html
4. http://api.symfony.com/4.0/Symfony/Component/Config/Loader/FileLoader.html
5. http://api.symfony.com/4.0/Symfony/Component/Config/Loader/LoaderResolver.html
6. http://api.symfony.com/4.0/Symfony/Component/Config/Loader/DelegatingLoader.html
7. http://api.symfony.com/4.0/Symfony/Component/Config/Loader/LoaderResolver.html
8. http://api.symfony.com/4.0/Symfony/Component/Config/Loader/LoaderResolver.html