From 1222fffdc24abe1427f96b7c879c3bb555f5f0b1 Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Fri, 30 Mar 2012 16:30:24 +0300 Subject: [PATCH 1/7] added cookbook entry on using Twig Extension --- cookbook/templating/twig_extension.rst | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 cookbook/templating/twig_extension.rst diff --git a/cookbook/templating/twig_extension.rst b/cookbook/templating/twig_extension.rst new file mode 100644 index 00000000000..d632d5da664 --- /dev/null +++ b/cookbook/templating/twig_extension.rst @@ -0,0 +1,102 @@ +.. index:: + single: Twig extensions + +How to write a custom Twig extension +============================================ + +The main motivation for writing an extension is to move often used code into a reusable class like adding support for internationalization. +An extension can define tags, filters, tests, operators, global variables, functions, and node visitors. + +Creating an extension also makes for a better separation of code that is executed at compilation time and code needed at runtime. As such, it makes your code faster. + +.. tip:: + + Before writing your own extensions, have a look at the `Twig official extension repository`_. + +Create the extension class +-------------------------- + +To get your custom functionality you must first create a Twig Extension class. +As an example we will create a price filter to format a given number into price. + + .. code-block:: php + + <?php + + // src/Acme/DemoBundle/Twig/AcmeExtension.php + + namespace Acme\DemoBundle\Twig; + + use Twig_Extension; + use Twig_Filter_Method; + use Twig_Function_Method; + + class AcmeExtension extends Twig_Extension + { + public function getFilters() + { + return array( + 'price' => new Twig_Filter_Method($this, 'priceFilter'), + ); + } + + public function priceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',') + { + $price = number_format($number, $decimals, $decPoint, $thousandsSep); + $price = '$' . $price; + + return $price; + } + + public function getName() + { + return 'acme_extension'; + } + } + +Register extension as a service +------------------------------- + +Now you must let Service Container know about your newly created Twig Extension: + +.. configuration-block:: + + .. code-block:: xml + + <!-- src/Acme/DemoBundle/Resources/config/services.xml --> + <services> + <service id="acme.twig.acme_extension" class="Acme\DemoBundle\Twig\AcmeExtension"> + <tag name="twig.extension" /> + </service> + </services> + + .. code-block:: yaml + + # src/Acme/DemoBundle/Resources/config/services.yml + services: + acme.twig.acme_extension: + class: Acme\DemoBundle\Twig\AcmeExtension + tags: + - { name: twig.extension } + + .. code-block:: php + + // src/Acme/DemoBundle/Resources/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + $acmeDefinition = new Definition('\Acme\DemoBundle\Twig\AcmeExtension'); + $acmeDefinition->addTag('twig.extension'); + $container->setDefinition('acme.twig.acme_extension', $acmeDefinition); + + +Using the custom extension +--------------------------- + +Using your newly created Twig Extension is no different than any other: + +.. code-block:: html+jinja + + {# outputs $5,500.00 #} + {{ '5500' | price }} + +.. _`Twig official extension repository`: http://github.com/fabpot/Twig-extensions \ No newline at end of file From 3970ba8704665b7773af32a50d33848655dac22b Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Fri, 30 Mar 2012 17:03:33 +0300 Subject: [PATCH 2/7] fixes for issues mentioned in comments by @weaverryan and @stof --- cookbook/templating/twig_extension.rst | 90 +++++++++++++++----------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/cookbook/templating/twig_extension.rst b/cookbook/templating/twig_extension.rst index d632d5da664..9aa5bdf4940 100644 --- a/cookbook/templating/twig_extension.rst +++ b/cookbook/templating/twig_extension.rst @@ -2,12 +2,16 @@ single: Twig extensions How to write a custom Twig extension -============================================ +==================================== -The main motivation for writing an extension is to move often used code into a reusable class like adding support for internationalization. -An extension can define tags, filters, tests, operators, global variables, functions, and node visitors. +The main motivation for writing an extension is to move often used code +into a reusable class like adding support for internationalization. +An extension can define tags, filters, tests, operators, global variables, +functions, and node visitors. -Creating an extension also makes for a better separation of code that is executed at compilation time and code needed at runtime. As such, it makes your code faster. +Creating an extension also makes for a better separation of code that is +executed at compilation time and code needed at runtime. As such, it makes +your code faster. .. tip:: @@ -17,42 +21,42 @@ Create the extension class -------------------------- To get your custom functionality you must first create a Twig Extension class. -As an example we will create a price filter to format a given number into price. +As an example we will create a price filter to format a given number into price:: - .. code-block:: php + // src/Acme/DemoBundle/Twig/AcmeExtension.php - <?php - - // src/Acme/DemoBundle/Twig/AcmeExtension.php + namespace Acme\DemoBundle\Twig; - namespace Acme\DemoBundle\Twig; + use Twig_Extension; + use Twig_Filter_Method; + use Twig_Function_Method; - use Twig_Extension; - use Twig_Filter_Method; - use Twig_Function_Method; + class AcmeExtension extends Twig_Extension + { + public function getFilters() + { + return array( + 'price' => new Twig_Filter_Method($this, 'priceFilter'), + ); + } + + public function priceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',') + { + $price = number_format($number, $decimals, $decPoint, $thousandsSep); + $price = '$' . $price; + + return $price; + } - class AcmeExtension extends Twig_Extension + public function getName() { - public function getFilters() - { - return array( - 'price' => new Twig_Filter_Method($this, 'priceFilter'), - ); - } - - public function priceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',') - { - $price = number_format($number, $decimals, $decPoint, $thousandsSep); - $price = '$' . $price; - - return $price; - } - - public function getName() - { - return 'acme_extension'; - } + return 'acme_extension'; } + } + +.. tip:: + + Along with custom filters, you can also add custom `functions` and register `global variables`. Register extension as a service ------------------------------- @@ -87,10 +91,16 @@ Now you must let Service Container know about your newly created Twig Extension: $acmeDefinition = new Definition('\Acme\DemoBundle\Twig\AcmeExtension'); $acmeDefinition->addTag('twig.extension'); $container->setDefinition('acme.twig.acme_extension', $acmeDefinition); - + +.. note:: + + Keep in mind that Twig Extensions are not lazily loaded. This means that + there's a higher chance that you'll get a **CircularReferenceException** + or a **ScopeWideningInjectionException** if any services + (or your Twig Extension in this case) are dependent on the request service. Using the custom extension ---------------------------- +-------------------------- Using your newly created Twig Extension is no different than any other: @@ -98,5 +108,13 @@ Using your newly created Twig Extension is no different than any other: {# outputs $5,500.00 #} {{ '5500' | price }} + +Learning further +---------------- + +For a more in-depth look into Twig Extensions, please take a look at the `Twig extensions documentation`_. -.. _`Twig official extension repository`: http://github.com/fabpot/Twig-extensions \ No newline at end of file +.. _`Twig official extension repository`: http://github.com/fabpot/Twig-extensions +.. _`Twig extensions documentation`: http://twig.sensiolabs.org/doc/extensions.html +.. _`global variables`: http://twig.sensiolabs.org/doc/extensions.html#globals +.. _`functions`: http://twig.sensiolabs.org/doc/extensions.html#functions \ No newline at end of file From 36335c7a68e7424f45cdda22a5bedd71624dd595 Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Fri, 30 Mar 2012 17:12:18 +0300 Subject: [PATCH 3/7] passing arguments to filter example --- cookbook/templating/twig_extension.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cookbook/templating/twig_extension.rst b/cookbook/templating/twig_extension.rst index 9aa5bdf4940..61bf5a7df7a 100644 --- a/cookbook/templating/twig_extension.rst +++ b/cookbook/templating/twig_extension.rst @@ -109,6 +109,13 @@ Using your newly created Twig Extension is no different than any other: {# outputs $5,500.00 #} {{ '5500' | price }} +Passing other arguments to your filter: + +.. code-block:: html+jinja + + {# outputs $5500,2516 #} + {{ '5500.25155' | price(4, ',', '') }} + Learning further ---------------- From c04b3e99631296c2f70aa5291c736a5c81ddaca3 Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Fri, 30 Mar 2012 17:16:20 +0300 Subject: [PATCH 4/7] remove html tags from code-block example since there's only twig in there --- cookbook/templating/twig_extension.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/templating/twig_extension.rst b/cookbook/templating/twig_extension.rst index 61bf5a7df7a..e1dd0e54488 100644 --- a/cookbook/templating/twig_extension.rst +++ b/cookbook/templating/twig_extension.rst @@ -104,14 +104,14 @@ Using the custom extension Using your newly created Twig Extension is no different than any other: -.. code-block:: html+jinja +.. code-block:: jinja {# outputs $5,500.00 #} {{ '5500' | price }} Passing other arguments to your filter: -.. code-block:: html+jinja +.. code-block:: jinja {# outputs $5500,2516 #} {{ '5500.25155' | price(4, ',', '') }} From 15439181f2ad7db1cdf68e523f0bdff0df27094f Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Fri, 30 Mar 2012 17:23:34 +0300 Subject: [PATCH 5/7] updated index/map to represent this cookbook entry, added it to Templating page reference --- book/templating.rst | 1 + cookbook/index.rst | 1 + cookbook/map.rst.inc | 1 + 3 files changed, 3 insertions(+) diff --git a/book/templating.rst b/book/templating.rst index 3b005642ea5..d6f184e94f8 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -1334,6 +1334,7 @@ Learn more from the Cookbook * :doc:`/cookbook/templating/PHP` * :doc:`/cookbook/controller/error_pages` +* :doc:`/cookbook/templating/twig_extension` .. _`Twig`: http://twig.sensiolabs.org .. _`KnpBundles.com`: http://knpbundles.com diff --git a/cookbook/index.rst b/cookbook/index.rst index 7e2da2c062f..7e84001f325 100644 --- a/cookbook/index.rst +++ b/cookbook/index.rst @@ -71,6 +71,7 @@ Cookbook templating/global_variables templating/PHP + templating/twig_extension logging/monolog logging/monolog_email diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 301ad1ea01f..f65a331dbcd 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -92,6 +92,7 @@ * :doc:`/cookbook/templating/global_variables` * :doc:`/cookbook/templating/PHP` + * :doc:`/cookbook/templating/twig_extension` * **Logging** From a6a60ff01da90cc1fe55e1d4201282f96945d1e2 Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Tue, 3 Apr 2012 09:49:22 +0300 Subject: [PATCH 6/7] capitalize nouns in titles --- cookbook/templating/twig_extension.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook/templating/twig_extension.rst b/cookbook/templating/twig_extension.rst index e1dd0e54488..7b9cbfe024d 100644 --- a/cookbook/templating/twig_extension.rst +++ b/cookbook/templating/twig_extension.rst @@ -1,7 +1,7 @@ .. index:: single: Twig extensions -How to write a custom Twig extension +How to write a custom Twig Extension ==================================== The main motivation for writing an extension is to move often used code @@ -17,7 +17,7 @@ your code faster. Before writing your own extensions, have a look at the `Twig official extension repository`_. -Create the extension class +Create the Extension Class -------------------------- To get your custom functionality you must first create a Twig Extension class. @@ -58,7 +58,7 @@ As an example we will create a price filter to format a given number into price: Along with custom filters, you can also add custom `functions` and register `global variables`. -Register extension as a service +Register an Extension as a Service ------------------------------- Now you must let Service Container know about your newly created Twig Extension: @@ -99,7 +99,7 @@ Now you must let Service Container know about your newly created Twig Extension: or a **ScopeWideningInjectionException** if any services (or your Twig Extension in this case) are dependent on the request service. -Using the custom extension +Using the custom Extension -------------------------- Using your newly created Twig Extension is no different than any other: From 61a5042868f7e66cdaca2be6bdeed0a94564d818 Mon Sep 17 00:00:00 2001 From: Roman Marintsenko <inoryy@gmail.com> Date: Tue, 3 Apr 2012 10:41:22 +0300 Subject: [PATCH 7/7] added a reference to scopes documentation --- cookbook/templating/twig_extension.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/cookbook/templating/twig_extension.rst b/cookbook/templating/twig_extension.rst index 7b9cbfe024d..6f105f4dfbc 100644 --- a/cookbook/templating/twig_extension.rst +++ b/cookbook/templating/twig_extension.rst @@ -98,6 +98,7 @@ Now you must let Service Container know about your newly created Twig Extension: there's a higher chance that you'll get a **CircularReferenceException** or a **ScopeWideningInjectionException** if any services (or your Twig Extension in this case) are dependent on the request service. + For more information take a look at :doc:`/cookbook/service_container/scopes`. Using the custom Extension --------------------------