Skip to content

Commit 7199104

Browse files
committed
minor #20879 [TwigBundle] Enable #[AsTwigFilter], #[AsTwigFunction] and #[AsTwigTest] (RisingSunLight42)
This PR was squashed before being merged into the 7.3 branch. Discussion ---------- [TwigBundle] Enable `#[AsTwigFilter]`, `#[AsTwigFunction]` and `#[AsTwigTest]` <!-- If your pull request fixes a BUG, use the oldest maintained branch that contains the bug (see https://symfony.com/releases for the list of maintained branches). If your pull request documents a NEW FEATURE, use the same Symfony branch where the feature was introduced (and `7.x` for features of unreleased versions). --> fix #20828 I did not listed the `AsTwigTest` attribute in the attributes list as no doc make mention of use case of this attribute. Do I had it anyway without any link to it (or a link to the [twig documentation](https://twig.symfony.com/doc/3.x/advanced.html#using-php-attributes-to-define-extensions))? Also I hope my wording is correct, feel free to ask me any adjustment 😄 I followed the plan of `@javiereguiluz` Commits ------- 15849ea [TwigBundle] Enable `#[AsTwigFilter]`, `#[AsTwigFunction]` and `#[AsTwigTest]`
2 parents 71c589f + 15849ea commit 7199104

File tree

3 files changed

+37
-40
lines changed

3 files changed

+37
-40
lines changed

quick_tour/the_architecture.rst

+6-13
Original file line numberDiff line numberDiff line change
@@ -159,29 +159,22 @@ Twig Extension & Autoconfiguration
159159
Thanks to Symfony's service handling, you can *extend* Symfony in many ways, like
160160
by creating an event subscriber or a security voter for complex authorization
161161
rules. Let's add a new filter to Twig called ``greet``. How? Create a class
162-
that extends ``AbstractExtension``::
162+
with your logic::
163163

164164
// src/Twig/GreetExtension.php
165165
namespace App\Twig;
166166

167167
use App\GreetingGenerator;
168-
use Twig\Extension\AbstractExtension;
169-
use Twig\TwigFilter;
168+
use Twig\Attribute\AsTwigFilter;
170169

171-
class GreetExtension extends AbstractExtension
170+
class GreetExtension
172171
{
173172
public function __construct(
174173
private GreetingGenerator $greetingGenerator,
175174
) {
176175
}
177176

178-
public function getFilters(): array
179-
{
180-
return [
181-
new TwigFilter('greet', [$this, 'greetUser']),
182-
];
183-
}
184-
177+
#[AsTwigFilter('greet')]
185178
public function greetUser(string $name): string
186179
{
187180
$greeting = $this->greetingGenerator->getRandomGreeting();
@@ -197,8 +190,8 @@ After creating just *one* file, you can use this immediately:
197190
{# templates/default/index.html.twig #}
198191
{# Will print something like "Hey Symfony!" #}
199192
<h1>{{ name|greet }}</h1>
200-
201-
How does this work? Symfony notices that your class extends ``AbstractExtension``
193+
194+
How does this work? Symfony notices that your class uses a Twig attribute
202195
and so *automatically* registers it as a Twig extension. This is called autoconfiguration,
203196
and it works for *many* many things. Create a class and then extend a base class
204197
(or implement an interface). Symfony takes care of the rest.

reference/attributes.rst

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ Twig
123123
~~~~
124124

125125
* :ref:`Template <templates-template-attribute>`
126+
* :ref:`AsTwigFilter <templates-twig-filter-attribute>`
127+
* :ref:`AsTwigFunction <templates-twig-function-attribute>`
126128

127129
Symfony UX
128130
~~~~~~~~~~

templates.rst

+29-27
Original file line numberDiff line numberDiff line change
@@ -1553,23 +1553,20 @@ as currency:
15531553
{# pass in the 3 optional arguments #}
15541554
{{ product.price|price(2, ',', '.') }}
15551555
1556-
Create a class that extends ``AbstractExtension`` and fill in the logic::
1556+
.. _templates-twig-filter-attribute:
1557+
1558+
Create a class with a method that contains the filter logic, then add
1559+
the ``#[AsTwigFilter]`` attribute to define the name and options of
1560+
the Twig filter::
15571561

15581562
// src/Twig/AppExtension.php
15591563
namespace App\Twig;
15601564

1561-
use Twig\Extension\AbstractExtension;
1562-
use Twig\TwigFilter;
1565+
use Twig\Attribute\AsTwigFilter;
15631566

1564-
class AppExtension extends AbstractExtension
1567+
class AppExtension
15651568
{
1566-
public function getFilters(): array
1567-
{
1568-
return [
1569-
new TwigFilter('price', [$this, 'formatPrice']),
1570-
];
1571-
}
1572-
1569+
#[AsTwigFilter('price')]
15731570
public function formatPrice(float $number, int $decimals = 0, string $decPoint = '.', string $thousandsSep = ','): string
15741571
{
15751572
$price = number_format($number, $decimals, $decPoint, $thousandsSep);
@@ -1579,24 +1576,19 @@ Create a class that extends ``AbstractExtension`` and fill in the logic::
15791576
}
15801577
}
15811578

1582-
If you want to create a function instead of a filter, define the
1583-
``getFunctions()`` method::
1579+
.. _templates-twig-function-attribute:
1580+
1581+
If you want to create a function instead of a filter, use the
1582+
``#[AsTwigFunction]`` attribute::
15841583

15851584
// src/Twig/AppExtension.php
15861585
namespace App\Twig;
15871586

1588-
use Twig\Extension\AbstractExtension;
1589-
use Twig\TwigFunction;
1587+
use Twig\Attribute\AsTwigFunction;
15901588

1591-
class AppExtension extends AbstractExtension
1589+
class AppExtension
15921590
{
1593-
public function getFunctions(): array
1594-
{
1595-
return [
1596-
new TwigFunction('area', [$this, 'calculateArea']),
1597-
];
1598-
}
1599-
1591+
#[AsTwigFunction('area')]
16001592
public function calculateArea(int $width, int $length): int
16011593
{
16021594
return $width * $length;
@@ -1608,6 +1600,16 @@ If you want to create a function instead of a filter, define the
16081600
Along with custom filters and functions, you can also register
16091601
`global variables`_.
16101602

1603+
.. versionadded:: 7.3
1604+
1605+
Support for the ``#[AsTwigFilter]``, ``#[AsTwigFunction]`` and ``#[AsTwigTest]`` attributes was introduced in Symfony 7.3.
1606+
Previously, you had to extend the ``AbstractExtension`` class, and override the
1607+
``getFilters()`` and ``getFunctions()`` methods.
1608+
1609+
When using autoconfiguration, the tag ``twig.attribute_extension`` is added automatically
1610+
when a Twig attribute is used on a method of a class. Otherwise, when autoconfiguration is not enabled,
1611+
it needs to be added in the service definition.
1612+
16111613
Register an Extension as a Service
16121614
..................................
16131615

@@ -1631,10 +1633,10 @@ this command to confirm that your new filter was successfully registered:
16311633
Creating Lazy-Loaded Twig Extensions
16321634
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16331635

1634-
Including the code of the custom filters/functions in the Twig extension class
1635-
is the simplest way to create extensions. However, Twig must initialize all
1636-
extensions before rendering any template, even if the template doesn't use an
1637-
extension.
1636+
When using attributes to extend Twig, the services are initialized only when
1637+
the functions or filters are used to render the template. But in case you use the
1638+
classic approach by extending the ``AbstractExtension`` class, Twig initializes all the extensions before
1639+
rendering any template, even if the extension is not used in the template.
16381640

16391641
If extensions don't define dependencies (i.e. if you don't inject services in
16401642
them) performance is not affected. However, if extensions define lots of complex

0 commit comments

Comments
 (0)