How to Create Custom TWIG-Filter in Drupal 8

4 min read

Send to you:

In Drupal 8 templating passed from commonly-used PHP Template to a new and progressive Twig templating engine long ago. Let’s learn how to create custom Twig-filters in Drupal 8.

In Twig templates, we can’t use traditional PHP-functions, and the syntax is also generally different. In Twig templates filters are used as a replacement for the functions. Filters are designated with a “pipe” symbol – “|”:

{{ data|filter() }}

or with additional arguments:

{{ data|filter(arg2, arg3) }}

Where “data” variable is the first argument of the filter, and the arguments in brackets are the second, the third, etc.

Twig Filters

Twig has a standard set of filters. You can familiarize yourself with them in the official documentation – http://twig.sensiolabs.org/doc/filters/index.html

But what if we need our own Twig-filter in Drupal 8, or in PHP language – a custom function? To do this, we need our custom module to declare the service – “twig_service” and prepare class which describes its functionality.

As an example, let’s set the task: create Twig-filter with currency conversion. Google Currency Converter API will be used for the conversion. We will send a request with required amount and currency. In response, we will get the result of the conversion according to the latest exchange rates.

Thus, we need to transfer three parameters to the filter:

  • the sum (amount);
  • original currency (curr_from);
  • target currency (curr_to).

That’s how the filter call will look:

{{ amount|filter(curr_from, curr_to) }}

Let’s define what we need to prepare for the demonstration of twig-filter creation. First of all, we need to create a custom module. How to do this can be found here. I have prepared a module called twig_filter. The module defines route and page controller, also defines twig-pattern and transfers the required for the filter parameters to the template.

Module file list

The module’s declaration file twig_filter.info.yml:

name: Twig Filter Test
type: module
description: 'Twig Filter Demonstration'
package: customs
version: '8.x'
core: '8.x'
project: 'twig_filter'

Route declaration file twig_filter.routing.yml:

twig_filter.result:
path: '/twig-filter/{curr_from}/{curr_to}/{amount}'
defaults:
  _controller: 'Drupaltwig_filterControllerTwigFilterController::testTwigPage'
  _title: 'Twig filter Page'
requirements:
  _permission: 'access content'

Controller Class file TwigFilterController.php:

<?php
/**
* @file
* Contains Drupaltwig_filterControllerTwigFilterController.
*/
namespace Drupaltwig_filterController;
use DrupalCoreControllerControllerBase;
/**
* Class TwigFilterController.
*
* @package Drupaltwig_filterController
*/
class TwigFilterController extends ControllerBase {
/**
 * {@inheritdoc}
 */
public function testTwigPage($curr_from, $curr_to, $amount) {
  // Construct element and it's data.
  $element = array(
    '#theme' => 'twig_filter_test_page',
    '#curr_from' => $curr_from,
    '#curr_to' => $curr_to,
    '#amount' => $amount,
  );
  return $element;
}
      }

Twig-template file twig-filter-test-page.html.twig  

(Explanation of the filter use):

<div>
  <h4>{% trans %}Google Currency API response results: {% endtrans %}</h4>
  {{ amount|currency(curr_from, curr_to) }}
</div>

Module functions File twig filter.module:

<?php
/**
* Implements hook_theme().
*/
function twig_filter_theme($existing, $type, $theme, $path) {
return [
  'twig_filter_test_page' => [
    'render element' => 'twig_filter_test_page',
    'path' => $path . '/templates',
    'template' => 'twig-filter-test-page',
    'variables' => [
      'curr_from' => NULL,
      'curr_to' => NULL,
      'amount' => NULL,
    ],
  ],
];
      }

Next, when we already have a module that defines a new route and page controller, we need to realize the following tasks:

  • declare twig_service module service;
  • create a class, which will describe the implementation of the functional Twig-filter.

To declare a service in the module, you need to create a file [module_name].services.yml. In my case, it will be twig_filter.services.yml:

Twig_filter.services

Write the following in the twig filter.services.yml file:

services:
  twig_filter.twig.twig_extension:
      class: Drupaltwig_filterTwigCurrencyTwigExtention
      public: false
      tags:
- { name: twig.extension }

Where we specify the file with twig-filter functionality class.

Now you should only create a class file that specifies the service.
In the “src” folder, which should be located in the root directory of the module, create “Twig” folder, and then create a file named CurrencyTwigExtention.php. We have the following structure of the module file:

structure of the module file

We make CurrencyTwigExtension.php file:

/**
* Class CurrencyTwigExtention.
*
* @package Drupaltwig_filterTwig
*/
class CurrencyTwigExtention extends Twig_Extension {
/**
 * Filter call.
 *
 * @return array|Twig_SimpleFilter[]
 */
public function getFilters() {
  return array(
    new Twig_SimpleFilter('currency', array($this, 'currencyCalcFilter')),
  );
}
/**
 * Use Google Currency Converter API.
 *
 * @param int $amount
 *    Amount.
 * @param string $curr_from
 *    From currency.
 * @param string $curr_to
 *    To currency.
 *
 * @return mixed
 *    API response.
 */
public function currencyCalcFilter($amount, $curr_from = 'USD', $curr_to = 'EUR') {
  $url = "http://www.google.com/finance/converter?a={$amount}&from={$curr_from}&to={$curr_to}";
  $request = curl_init();
  $timeOut = 100;
  curl_setopt($request, CURLOPT_URL, $url);
  curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($request, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
  curl_setopt($request, CURLOPT_CONNECTTIMEOUT, $timeOut);
  $response = curl_exec($request);
  curl_close($request);
  preg_match("/<div id=currency_converter_result>(.*)<span class=bld>(.*)</span>/", $response, $converted);
  $output = array(
    '#type' => 'markup',
    '#markup' => sprintf("<div>%s</div>", implode('', [$converted[1], $converted[2]])),
  );
  return $output;
}
/**
 * Get filter name.
 *
 * @return string
 *    Filter name.
 */
public function getName() {
  return 'twig_filter.twig_extension';
}
        }

When using |currency Twig-filter, currencyCalcFilter() the method tethered to it is called, in which we make HTTP-request to Google currency converter API with the required parameters. And then we cut out the useful text from the reply with a regular expression and give the results via a build-container for rendering content.

If you did everything right, when after navigating /twig-filter/USD/UAH/1500 page, we get the following result:

Twig filter page

Don’t forget to clear the cache after changes in the twig templates or module code.
We hope this article was useful for you, and you are ready to create a custom filter. But if you need some help, feel free to contact us and we’ll solve your issues related to Drupal development.

5.0/5.0

Article rating (1 Reviews)

Do you find this article useful? Please, let us know your opinion and rate the post!

  • Not bad
  • Good
  • Very Good
  • Great
  • Awesome