Twig is a part of the Symfony framework and was introduced as a template engine. Drupal 8 also uses twig as a template engine.

We can modify incoming data to twig using Drupal 8 template hooks but we also need some quick filter and dynamic functions that we can directly inject into a particular template.

Drupal 8 provides a way to create a custom twig extension, Let’s see how we can do this

  1. Declare your custom module using the info.yml file. Here our example module name is “Twig Extension” (twig_extension). [file name:- twig_extension.info.yml]
    name: Twig Extension
    type: module
    description: 'Twig custom extension - Filter and function'
    package: Theme
    core: 8.x
  2. Now declare a twig extension service as below. [file name:-twig_extension.services.yml]
    services:
      twig_extension.function:
        class: Drupal\twig_extension\TwigExtension\TwigFunctionExtension
        tags:
          - { name: twig.extension }
      twig_extension.filter:
        arguments: ['@renderer']
        class: Drupal\twig_extension\TwigExtension\TwigFilterExtension
        tags:
          - { name: twig.extension }
    Make sure to use service tag twig.extension, This will tell Drupal 8 that this service is for twig extension.
  3. Create a twig filter using Twig_SimpleFilter class. [file name:-TwigFilterExtension.php]
    <?php
    namespace Drupal\twig_extension\TwigExtension;
    /**
     * Class TwigFilterExtension.
     */
    class TwigFilterExtension extends \Twig_Extension{
      /**
       * Declare your custom twig filter here
       *
       * @return array|\Twig_SimpleFilter[]
       */
      public function getFilters()
      {
        return [ 
          new \Twig_SimpleFilter(
            'remove_links', 
            array($this, 'removeLinks')
          )
        ];
      }
      /**
       * Function to remove only links from the html
       * @param $string
       *  Html as string
       *
       * @return string
       *  Filtered html
       */
      public static function removeLinks($string)
      {
        return preg_replace('#<a.*?>(.*?)</a>#i',
          '\1',
          $string);
      }
      /**
       * {@inheritdoc}
       * @return string
       */
      public function getName()
      {
        return 'twig_extension.filter';
      }
    }
  4. Create a twig function using class Twig_SimpleFunction. [file name:- TwigFunctionExtension.php]
    <?php
    namespace Drupal\twig_extension\TwigExtension;
    /**
     * Class TwigFunctionExtension.
     */
    class TwigFunctionExtension extends \Twig_Extension {
      /**
       * Declare your custom twig extension here
       *
       * @return array|\Twig_SimpleFunction[]
       */
      public function getFunctions() {
        return array(
          new \Twig_SimpleFunction('display_block_by_id',
            array($this, 'display_block'),
            array('is_safe' => array('html'))
          )
        );
      }
      /**
       * Function to get and render block by id
       * @param $block_id
       *  Block id to render
       *
       * @return array
       */
      public function display_block($block_id) {
        $block = \Drupal\block\Entity\Block::load($block_id);
        return \Drupal::entityTypeManager()
          ->getViewBuilder('block')
          ->view($block);
      }
      /**
       * {@inheritdoc}
       * @return string
       */
      public function getName() {
        return 'twig_extension.function';
      }
    }

We rarely need to develop a custom twig function and filter in Drupal 8 but we can successfully do this as described above.