SymfonyのTwigを拡張!カスタムフィルターや関数を追加

symfony-twig-extension
  • URLをコピーしました!

SymfonyTwig内で正規表現を使ったパターンマッチングからの置換をしたい場面に遭遇した。
しかし、いくら調べてもSymfony標準のフィルターには私が望むものはありませんでしたが、カスタムフィルター関数を作成する方法があるようなのでメモしておきます。

目次

PHPのpreg_replace()で置換したい!

最終的にやりたいことは、Twig内でHTMLのimgタグからalt属性の文字だけを抜き出して、imgタグと置き換えること。
これだけだと需要がないように思うが、フィルター自体はPHPの[preg_replace()]関数と同様の動きをするので使い回しが可能です。
Twig側では以下のように置換できるようにします。

{{ data.content|preg_replace('/<img(.*?)alt="(.*?)"(.*?)>/si', "$2")|striptags }}

[data.content]はHTMLコンテンツ、[preg_replace()]フィルターPHP同様の正規表現を使ったパターンマッチングを行い、Symfonyの標準フィルター[striptags]でHTMLタグを削除するといった感じです。

Twigの拡張

それでは参考サイトを基に、Twig拡張していきましょう。
今回は、カスタムフィルター関数のみとします。
フィルターに関しては上記で説明しましたが、関数に関しては、独自CSRFトークンを生成する関数を作ります。
こちらも需要がないでしょうが、サービスコンテナの渡し方についてもメモしておきたかったので。

今回は触れませんが、グローバル変数もここで設定できるようです。
ブラウザの翻訳機能を使えば英語の本家ドキュメントの方がより詳しいです。

あわせて読みたい
Creating and Using Templates (Symfony 5.x Docs) A template is the best way to organize and render HTML from inside your application, whether you need to render HTML from a controller or generate the contents ...

独自フィルターと独自関数を追加

例としてバンドル名はAppBundleとします。
AppBundle直下にTwigフォルダを作成して、その下に[AppExtension.php](ファイル名は任意)ファイルを作成します。
symfony/src/AppBundle/Twig/AppExtension.php

<?php
namespace AppBundle\Twig;

use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class AppExtension extends Twig_Extension
{
    public function __construct(Container $container)
    {
        $this->container = $container;
        $this->request = $container->get('request');
        $this->session = $container->get('session');
    }
    
    public function getFilters()
    {
        return [
            new Twig_SimpleFilter('preg_replace', [$this, 'pregReplaceFilter']),
        ];
    }    public function getFunctions()
    {
        return [
            new Twig_SimpleFunction('_token', [$this, 'csrfToken']),
        ];
    }
    
    public function pregReplaceFilter($subject, $pattern = '', $replacement = '')
    {
        return preg_replace($pattern, $replacement, $subject);
    }
    
    public function csrfToken()
    {
        $did = $this->request->get('id');
        $token = '';
        if ($did) {
            $token = md5($this->container->getParameter('secret') . $id . date('YmdHis'));
            $this->session->set($id . '_token', $token);
        }
        return $token;
    }
}

解説

[getFilters()]でフィルターを、[getFunctions()]で関数を追加できます。
使いの仕方はどちらも同じで、returnの配列の中にカンマ区切りで追加します。

return [
    new Twig_SimpleFilter('[Twig内のフィルター名]', [$this, '[同クラス内で実行する関数]')),
];

つまり、Twig側でTwig_SimpleFilter()第1引数を書くと、第2引数で指定した関数が実行されるという仕組みです。

サービスの登録

しかし、これだけでは使えません。
作った拡張機能を利用できるように設定ファイルで設定する必要があります。

YAMLに追加する

Symfonyの設定は最終的にはconfig.ymlに集約されるので、[app/Resourcesconfig]フォルダ以下の.ymlファイルならどこに書いても良いのですが、せっかくサービスと名の付くservices.ymlがあるので、これに書きたいと思います。
symfony/app/Resources/config/services.yml

services:
    app.twig_extension:
        class: AppBundleTwigAppExtension
        arguments: ["@service_container"]
        public: false
        tags:
            - { name: twig.extension }

ここでは、前述の通りサービスコンテナの使い方もメモしておきたいので、

arguments: ["@service_container"]

がキーになります。
こうすることで初めてAppExtension.phpコンストラクタContainerが使えるようになります。以上です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次