7

I'm trying to create a custom Twig filter in Drupal 8. The goal is to use my custom filter in a template like so:

{{ a_variable|myfilter }}

I have created a custom module with 3 files:

MODULE.info.yml
MODULE.services.yml
src/TwigExtension/MyExtension.php

The MODULE.info.yml file contains the usual values.

The MODULE.services.yml file contains:

services:
  MODULE.twig_extension:
#   arguments: ['@renderer']  #  <-- Initial code (USELESS)
    class: Drupal\MODULE\TwigExtension\MyExtension
    tags:
      - { name: twig.extension }

The src/TwigExtension/MyExtension.php file contains:

namespace Drupal\MODULE\TwigExtension;

// use Drupal\Core\Template\TwigExtension;  // <-- Initial code (WRONG)

class MyExtension extends \Twig_Extension {    
// class MyExtension extends TwigExtension {  // <-- Initial code (WRONG)

  /**
   * Generates a list of all Twig filters that this extension defines.
   */
  public function getFilters() {
    return [
      new \Twig_SimpleFilter('myfilter', array($this, 'myFilter')),
    ];
  }

  /**
   * Gets a unique identifier for this Twig extension.
   */
  public function getName() {
    return 'MODULE.twig_extension';
  }

  /**
   * Replaces all instances of "animal" in a string with "plant".
   */
  public static function myFilter($string) {
    return str_replace(array('animal'), array('plant'), $string);
  }

}

My initial code got following error: "Call to a member function generateFromRoute() on a non-object in /core/lib/Drupal/Core/Template/TwigExtension.php on line 224".

But I have now corrected the code following lauriii's answer and it works perfectly!

  • 1
    Hm, I have checked mine implementation and all seems fine. Are yo usure the error comes from your extension? Maybe you are calling bad function in twig somewhere? Try to switch to some core theme and call your function n there. – user21641 Dec 16 '15 at 15:21
  • It was a subtle error, replacing TwigExtension with \Twig_Extension. ;-) – AngularChef Dec 16 '15 at 18:55
  • 1
    leopathu.in/content/create-custom-twig-filter-drupal-8 This article explained well about the custom twig filter with the example and also you could download the sample code from the page. – Leopathu Aug 10 '16 at 9:00
8

The problem in the code above is that your Twig extension class is extending the internal Drupal Twig extension class. That breaks the Twig extensions added by Drupal core and that's why you are getting the error.

To fix this, you should make your Twig extensions extend Twigs internal Twig extension class. Your class should be defined like this:

class MyExtension extends \Twig_Extension {

After making that change, you can also remove arguments set for that class from the MODULE.services.yml

|improve this answer|||||
  • Awesome, it works! Thank you so much, lauriii. I will update my original code to reflect your answer. – AngularChef Dec 16 '15 at 18:22
  • Strange... My initial code was modeled after that found in the twig_extension_test core module. – AngularChef Dec 16 '15 at 18:28
  • There is a patch pending to fix twig_extension_test. Test modules are not always the best examples unfortunately. – Cottser Dec 27 '15 at 13:51
0

the above sample is still off.. (ie: the 'arguments' clause in .services does seem to be needed)

take a look at /core/modules/system/tests/modules/twig_extension_test to model a twig filter and function from!

|improve this answer|||||
  • follow up: for whatever reason... the twig_extension_test seems to only works when viewed under an /admin path... – skaught Apr 20 '16 at 12:51
0

it seems we need to use \Twig_Extension class more directly.

MODULE.services.yml services: MODULE.twig.filters: arguments: ['@renderer'] class: Drupal\MODULE\TwigExtension\HexToRgb tags: - { name: twig.extension }

/src/TwigExtension/HexToRgb.php

/**
 * @file
 * Contains Drupal\MODULE\TwigExtension.
 */

namespace Drupal\MODULE\TwigExtension;


/**
 * A Twig extension (filter) converts hex color to rgb.
 */
class HexToRgb extends \Twig_Extension {

  /**
   * Generates a list of all Twig filters that this extension defines.
   */
  public function getFilters() {
    return array(
      new \Twig_SimpleFilter('hexToRGB', [$this, 'hexToRGB'], ['is_safe' => ['html']]),
      new \Twig_SimpleFilter('rangeToPercent', [$this, 'rangeToPercent'], ['is_safe' => ['html']]),
    );
  }

  /**
   * Gets a unique identifier for this Twig extension.
   */
  public function getName() {
    return 'MODULE.twig.filters';
  }

  /**
   * convert 3 or 6 char hex color to comma seperated RGB colors
   */
  public static function hexToRgb($hex=000000) {
    $r = $g = $b = FALSE;
    $hex = str_replace("#", "", $hex);

    if(strlen($hex) == 3) {
      $r = hexdec(substr($hex, 0, 1).substr($hex, 0, 1));
      $g = hexdec(substr($hex, 1, 1).substr($hex, 1, 1));
      $b = hexdec(substr($hex, 2, 1).substr($hex, 2, 1));
    } else {
      $r = hexdec(substr($hex, 0, 2));
      $g = hexdec(substr($hex, 2, 2));
      $b = hexdec(substr($hex, 4, 2));
    }

    $rgb = array($r, $g, $b);

    return implode(",", $rgb);
  }

  /**
   * convert range (0 to 100) to a percent with 2 decimals
   */
  public static function rangeToPercent($range=0) {
    return round(($range/100), 2);
  }


}

|improve this answer|||||
  • arguments: ['@renderer'] is unnecessary because the \Twig_Extension class has no constructor. – Tim Mar 27 at 7:51
-1

Try https://www.drupal.org/project/twig_extender . Add a plugin system for custom twig functions and filters

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.