Symfony2のTwigを拡張!カスタムフィルターや関数を追加する方法

SymfonyのTwig内で正規表現を使ったパターンマッチングからの置換をしたい場面に遭遇した。
しかし、いくら調べてもSymfony標準のフィルターには私が望むものはありませんでしたが、独自フィルターを作成する方法があるようなのでメモしておきます。
PHPのpreg_replace()で置換したい!
最終的にやりたいことは、Twig内でHTMLのimgタグからalt属性の文字だけを抜き出して、imgタグと置き換えること。
これだけだと需要がないように思うが、フィルター自体はPHPのpreg_replace()
関数と同様の動きをするので使い回しが可能です。
Twig側では以下のように置換できるようにします。
data.content
はHTMLコンテンツ、preg_replace()
フィルターでPHP同様の正規表現を使ったパターンマッチングを行い、Symfonyの標準フィルターstriptagsでHTMLタグを削除するといった感じです。
Twigの拡張
それでは参考サイトを基に、Twigを拡張していきましょう。
今回は、独自フィルターと独自関数のみとします。
フィルターに関しては上記で説明しましたが、関数に関しては、独自CSRFトークンを生成する関数を作ります。
こちらも需要がないでしょうが、サービスコンテナの渡し方についてもメモしておきたかったので。
symfony公式にはfilterしか書いてないのでよく使いそうなfunction,filter,globalのtwig拡張のメモ。###クラス例```namespace CommonBundle\Twig\Extensi... symfony twig拡張メモ - Qiita - Qiita |
ブラウザの翻訳機能を使えば英語の本家ドキュメントの方がより詳しいです。
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 defin... How to Write a custom Twig Extension (Symfony 2.8 Docs) - symfony.com |
Twig - The flexible, fast, and secure template engine for PHP Extending Twig - Documentation - Twig - The flexible, fast, and secure PHP te... - twig.symfony.com |
独自フィルターと独自関数を追加
例としてバンドル名は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\Resources\config\
フォルダ以下の.ymlファイルならどこに書いても良いのですが、せっかくサービスと名の付くservices.ymlがあるので、これに書きたいと思います。
symfony\app\Resources\config\services.yml
services:
app.twig_extension:
class: AppBundle\Twig\AppExtension
arguments: ["@service_container"]
public: false
tags:
- { name: twig.extension }
ここでは、前述の通りサービスコンテナの使い方もメモしておきたいので、
arguments: ["@service_container"]
がキーになります。
こうすることで初めてAppExtension.phpのコンストラクタでContainerが使えるようになります。
以上です。
コメント
コメントを投稿