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

Skip to content

Commit 1c48a83

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

File tree

4 files changed

+207
-0
lines changed

4 files changed

+207
-0
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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 need
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/OverrideAssetDefaultPackagePass.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+
< 8000 code>36+
class OverrideAssetDefaultPackagePass implements CompilerPassInterface
37+
{
38+
public function process(ContainerBuilder $container)
39+
{
40+
$definition = $container->getDefinition('assets.packages');
41+
$definition->replaceArgument(0, new Reference('app.assets.empty_package'));
42+
}
43+
}
44+
45+
The code above fetches the service definition of the asset packages registry, and replaces
46+
its first argument (the default package).
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\OverrideAssetDefaultPackagePass;
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 OverrideAssetDefaultPackagePass());
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.empty_package:
86+
class: Symfony\Component\Asset\Package
87+
arguments:
88+
- @app.assets.buster_version_strategy
89+
public: false
90+
91+
app.assets.buster_version_strategy:
92+
class: AppBundle\Asset\VersionStrategy\BusterVersionStrategy
93+
F438 arguments:
94+
- manifest_path: "%kernel.root_dir%/../busters.json"
95+
format: "%%s?version=%%s"
96+
public: false
97+
98+
.. code-block:: xml
99+
100+
<!-- app/config/services.xml -->
101+
<?xml version="1.0" encoding="UTF-8" ?>
102+
<container xmlns="http://symfony.com/schema/dic/services"
103+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
104+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
105+
106+
<services>
107+
108+
<service id="app.assets.empty_package" class="Symfony\Component\Asset\Package" public="false">
109+
<argument type="service" id="app.assets.buster_version_strategy" />
110+
</service>
111+
112+
<service id="app.assets.buster_version_strategy" class="AppBundle\Asset\VersionStrategy\BusterVersionStrategy" public="false">
113+
<argument type="collection">
114+
<argument key="manifest_path">%kernel.root_dir%/../busters.json</argument>
115+
<argument key="format">%%s?version=%%s</argument>
116+
</argument>
117+
</service>
118+
119+
</services>
120+
</container>
121+
122+
Implement VersionStrategyInterface
123+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124+
125+
.. code-block:: php
126+
127+
// src/AppBundle/Asset/VersionStrategy/BusterVersionStrategy.php
128+
namespace AppBundle\Asset\VersionStrategy;
129+
130+
use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;
131+
132+
class BusterVersionStrategy implements VersionStrategyInterface
133+
{
134+
/**
135+
* @var string
136+
*/
137+
private $manifestPath;
138+
139+
/**
140+
* @var string
141+
*/
142+
private $format;
143+
144+
/**
145+
* @var string[]
146+
*/
147+
private $hashes;
148+
149+
/**
150+
* @param array $options {
151+
* @var string $manifest_path
152+
* @var string|null $format
153+
* }
154+
*/
155+
public function __construct(array $options)
156+
{
157+
$this->manifestPath = $options['manifest_path'];
158+
$this->format = isset($options['format']) ? $options['format'] : '%s?%s';
159+
}
160+
161+
public function getVersion($path)
162+
{
163+
if (!is_array($this->hashes)) {
164+
$this->hashes = $this->loadManifest(array(
165+
'file_path' => realpath($this->manifestPath),
166+
));
167+
}
168+
169+
return isset($this->hashes[$path]) ? $this->hashes[$path] : '';
170+
}
171+
172+
public function applyVersion($path)
173+
{
174+
$version = $this->getVersion($path);
175+
176+
if ('' === $version) {
177+
return $path;
178+
}
179+
180+
$versionized = sprintf($this->format, ltrim($path, '/'), $version);
181+
182+
if ($path && '/' === $path[0]) {
183+
return '/'.$versionized;
184+
}
185+
186+
return $versionized;
187+
}
188+
189+
private function loadManifest(array $options)
190+
{
191+
$hashes = json_decode(file_get_contents($options['file_path']), $assoc = true);
192+
193+
return $hashes;
194+
}
195+
}
196+
197+
.. _`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