Symfony 3: some new features that i like

New in Symfony 3.3: Getter injection

As part of our experimental features program, in Symfony 3.3 we’ve added a new feature called getter injection. This adds up to the usual mechanisms used for dependency injection and doesn’t replace any of them. Instead, it provides an additional way that fits some specific use cases.

Getter injection allows the dependency injection container to leverage classes that provide inheritance-based extension points that matches the following requirements: public or protected methods with zero arguments and free of side-effects.

Some examples found while grepping Symfony and its vendors:

  • Kernel::getRootDir/CacheDir/LogDir() in HttpKernel
  • SessionListener::getSession() in HttpKernel also
  • AbstractBaseFactory::getGenerator() in ProxyManager

This is only a small subset of all the classes that apply this flavor of the open/closed principle in Symfony core and elsewhere. As shown in the examples, this applies both to objects injection (services) and to values injection (parameters).

Getter injection is a way to turn these classes into DI candidates via simple DI configuration. In Yaml, taking the SessionListener::getSession() example, this could look like:

1
2
3
4
services:
  SessionListener:
    getters:
      getSession: '@session'

In practice, this tells the Symfony Dependency Injection Container to create an anonymous inheritance-proxy class like this one:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$sessionListener = new class ($container) extends SessionListener {
    private $container;

    function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getSession()
    {
        return $this->container->get('session');
    }
};

See More

New in Symfony 3.3: Simple Cache

In Symfony 3.1, we added a new Cache component that implemented the PSR-6: Caching Interface standard. In Symfony 3.2 we improved the component with tagged caches and other improvements.

Although the Cache component provides everything that enterprise applications need, for smaller applications it’s a bit cumbersome to use. For example, to use a file system based cache to store, fetch and delete a simple variable, you must do the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

$cache = new FilesystemAdapter();

// save an item in the cache
$numProducts = $cache->getItem('stats.num_products');
$numProducts->set(4711);
$cache->save($numProducts);

// fetch the item from the cache
$numProducts = $cache->getItem('stats.num_products');
if (!$numProducts->isHit()) {
    // ... item does not exist in the cache
} else {
    $total = $numProducts->get();
}

// remove the item from the cache
$cache->deleteItem('stats.num_products');

In Symfony 3.3 we decided to improve the Cache component by implementing a related standard called PSR-16: Common Interface for Caching Libraries. In short, it’s a simplified cache mechanism to store, fetch and remove items from a cache. This is how the previous example would look with the new cache:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
use Symfony\Component\Cache\Simple\FilesystemCache;

$cache = new FilesystemCache();

// save an item in the cache
$cache->set('stats.num_products', 4711);

// fetch the item from the cache
if (!$cache->has('stats.num_products')) {
    // ... item does not exist in the cache
} else {
    $total = $cache->get('stats.num_products');
}

// remove the item from the cache
$cache->delete('stats.num_products');

The simple cache also allows to define default values when items don’t exist in the cache and it defines the setMultiple(), getMultiple() and deleteMultiple() methods to work with several items simultaneously.

Both the regular cache and the simple cache support the same cache adapters (file system, Redis, Memcache, etc.) and both provide similar performance, so the decision to choose one or another should be based on the features that you’ll need for the cache.

 

New in Symfony 3.3: Asset preloading with HTTP/2 Push

One of the most relevant new features proposed by HTTP/2 to improve the loading of web pages is called Server Push. HTTP/2 Push allows a web server to send resources to a web browser before the browser gets to request them.

In Symfony 3.3 we added HTTP/2 Push support for web assets (CSS, JS, images) to allow preloading them as explained in the Preload W3C Working Draft. In practice, and following the traditional Symfony philosophy of using composition, the new feature is enabled by wrapping your assets with the new preload() function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<head>
    {# by default, assets are pushed #}
    <link href="{{ preload(asset('/css/app.css')) }}">
    {# ... but you can disable pushing... #}
    <link href="{{ preload(asset('/css/app.css'), { nopush: true }) }}">
    {# ... and you can also explicit the asset type #}
    <link href="{{ preload(asset('/css/app.css'), { as: 'style' }) }}">
    ...
</head>
<body>
    ...
    /spanspan%20class=
</body>

Behind the scenes, the preload() function adds a Link HTTP header that is processed by intermediate proxies compatible with HTTP/2:

1
2
3
4
HTTP/1.1 200 OK
Content-Type: text/html
...
Link: </css/app.css>; rel=preload,</cjs/app.js>; rel=preload

An added bonus of using this technique is that all those assets are downloaded using just one connection, improving the page speed dramatically.

Sources:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s