8000 Cookbook entry: Asset - Custom Version Strategy · symfony/symfony-docs@79564d2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 79564d2

Browse files
committed
Cookbook entry: Asset - Custom Version Strategy
1 parent eff6e9c commit 79564d2

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
.. index::
2+
single: Asset; Custom Version Strategy
3+
4+
How to use a Custom Version Strategy for Assets
5+
===============================================
6+
7+
Out of the box, Symfony exposes configuration options which allow you to
8+
specify the assets version and the format of the versioned path. If you require
9+
more control, you need to create a custom version strategy.
10+
11+
.. versionadded:: 2.7
12+
The Asset component was introduced in Symfony 2.7.
13+
14+
Default Package
15+
---------------
16+
17+
The default package is the `''` package. It is used when you do not specify
18+
a package name in the :ref:`asset <reference-twig-function-asset>` Twig function.
19+
In order to override the version strategy used by the default package,
20+
it is necessary to add a compiler pass.
21+
22+
This example shows how to integrate with `gulp-buster`_.
23+
24+
Create Compiler Pass
25+
~~~~~~~~~~~~~~~~~~~~
26+
27+
.. code-block:: php
28+
29+
// src/AppBundle/DependencyInjection/Compiler/OverrideAssetsDefaultPackagePass.php
30+
namespace AppBundle\DependencyInjection\Compiler;
31+
32+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
33+
use Symfony\Component\DependencyInjection\ContainerBuilder;
34+
use Symfony\Component\DependencyInjection\Reference;
35+
36+
class OverrideAssetsDefaultPackagePass implements CompilerPassInterface
37+
{
38+
public function process(ContainerBuilder $container)
39+
{
40+
$definition = $container->getDefinition('assets._default_package');
41+
$definition->replaceArgument(1, new Reference('app.assets.buster_version_strategy'));
42+
}
43+
}
44+
45+
The code above fetches the service definition of the default package, and replaces
46+
its 2nd argument (the version strategy).
47+
48+
Register Compiler Pass
49+
~~~~~~~~~~~~~~~~~~~~~~
50+
51+
.. code-block:: php
52+
53+
// src/AppBundle/AppBundle.php
54+
namespace AppBundle;
55+
56+
use AppBundle\DependencyInjection\Compiler\OverrideAssetsDefaultPackagePass;
57+
use Symfony\Component\DependencyInjection\ContainerBuilder;
58+
use Symfony\Component\HttpKernel\Bundle\Bundle;
59+
60+
class AppBundle extends Bundle
61+
{
62+
public function build(ContainerBuilder $container)
63+
{
64+
parent::build($container);
65+
66+
// only register in prod environment
67+
if ('prod' === $container->getParameter('kernel.environment')) {
68+
$container->addCompilerPass(new OverrideAssetsDefaultPackagePass());
69+
}
70+
}
71+
}
72+
73+
See :doc:`/cookbook/service_container/compiler_passes` for more information
74+
on how to use compiler passes.
75+
76+
Register Services
77+
~~~~~~~~~~~~~~~~~
78+
79+
.. configuration-block::
80+
81+
.. code-block:: yaml
82+
83+
# app/config/services.yml
84+
services:
85+
app.assets.buster_version_strategy:
86+
class: AppBundle\Asset\VersionStrategy\BusterVersionStrategy
87+
arguments:
88+
- manifest_path: "%kernel.root_dir%/../busters.json"
89+
format: "%%s?version=%%s"
90+
public: false
91+
92+
.. code-block:: xml
93+
94+
<!-- app/config/services.xml -->
95+
<?xml version="1.0" encoding="UTF-8" ?>
96+
<container xmlns="http://symfony.com/schema/dic/services"
97+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
98+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
99+
100+
<services>
101+
102+
<service id="app.assets.buster_version_strategy" class="AppBundle\Asset\VersionStrategy\BusterVersionStrategy" public="false">
103+
<argument type="collection">
104+
<argument key="manifest_path">%kernel.root_dir%/../busters.json</argument>
105+
<argument key="format">%%s?version=%%s</argument>
106+
</argument>
107+
</service>
108+
109+
</services>
110+
</container>
111+
112+
.. code-block:: php
113+
114+
// app/config/services.php
115+
use Symfony\Component\DependencyInjection\Definition;
116+
117+
$definition = new Definition(
118+
'AppBundle\Asset\VersionStrategy\BusterVersionStrategy',
119+
array(
120+
array(
121+
'manifest_path' => '%kernel.root_dir%/../busters.json',
122+
'format' => '%%s?version=%%s',
123+
),
124+
)
125+
);
126+
$definition->setPublic(false);
127+
128+
$container->setDefinition('app.assets.buster_version_strategy', $definition);
129+
130+
Implement VersionStrategyInterface
131+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132+
133+
.. code-block:: php
134+
135+
// src/AppBundle/Asset/VersionStrategy/BusterVersionStrategy.php
136+
namespace AppBundle\Asset\VersionStrategy;
137+
138+
use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;
139+
140+
class BusterVersionStrategy implements VersionStrategyInterface
141+
{
142+
/**
143+
* @var string
144+
*/
145+
private $manifestPath;
146+
147+
/**
148+
* @var string
149+
*/
150+
private $format;
151+
152+
/**
153+
* @var string[]
154+
*/
155+
private $hashes;
156+
157+
/**
158+
* @param array $options {
159+
* @var string $manifest_path
160+
* @var string|null $format
161+
* }
162+
*/
163+
public function __construct(array $options)
164+
{
165+
$this->manifestPath = $options['manifest_path'];
166+
$this->format = isset($options['format']) ? $options['format'] : '%s?%s';
167+
}
168+
169+
public function getVersion($path)
170+
{
171+
if (!is_array($this->hashes)) {
172+
$this->hashes = $this->loadManifest(array(
173+
'file_path' => realpath($this->manifestPath),
174+
));
175+
}
176+
177+
return isset($this->hashes[$path]) ? $this->hashes[$path] : '';
178+
}
179+
180+
public function applyVersion($path)
181+
{
182+
$version = $this->getVersion($path);
183+
184+
if ('' === $version) {
185+
return $path;
186+
}
187+
188+
$versionized = sprintf($this->format, ltrim($path, '/'), $version);
189+
190+
if ($path && '/' === $path[0]) {
191+
return '/'.$versionized;
192+
}
193+
194+
return $versionized;
195+
}
196+
197+
private function loadManifest(array $options)
198+
{
199+
$hashes = json_decode(file_get_contents($options['file_path']), $assoc = true);
200+
201+
return $hashes;
202+
}
203+
}
204+
205+
.. _`gulp-buster`: https://www.npmjs.com/package/gulp-buster

cookbook/asset/index.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Asset
2+
=====
3+
4+
.. toctree::
5+
:maxdepth: 2
6+
7+
custom_version_strategy

cookbook/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ The Cookbook
44
.. toctree::
55
:hidden:
66

7+
asset/index
78
assetic/index
89
bundles/index
910
cache/index

reference/twig_reference.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ Returns an instance of ``ControllerReference`` to be used with functions
9393
like :ref:`render() <reference-twig-function-render>` and
9494
:ref:`render_esi() <reference-twig-function-render-esi>`.
9595

96+
.. _reference-twig-function-asset:
97+
9698
asset
9799
~~~~~
98100

0 commit comments

Comments
 (0)
0