Twigのカスタム関数・フィルターの作り方を徹底解説!初心者向けSymfonyテンプレート講座
生徒
「Twigで独自の関数やフィルターって作れますか? 既存のじゃ足りなくて…」
先生
「はい、Twigではカスタム関数やフィルターを自分で定義することができます。表示を自由にコントロールできますよ。」
生徒
「でも関数とかフィルターって難しそうです…初心者でも作れますか?」
先生
「もちろんです。実際の例を使いながら、やさしく説明していきますね!」
1. Twigのカスタム関数・フィルターとは?
Twigには、表示を便利にするための「関数(Functions)」と「フィルター(Filters)」という2つの強力な武器があります。これらを使いこなすと、PHP側で複雑なロジックを組まなくても、テンプレート側で直感的にデータを整形できるようになります。
● 関数(Functions)とは?
特定の「命令」を出して、新しいデータを作り出したり、何かを呼び出したりするものです。Excelの関数のイメージに近く、単体で動作します。
【記述例】
{{ get_current_time() }}
● フィルター(Filters)とは?
すでにある「データ」を加工・変形するためのものです。パイプ記号(|)を使って、左にあるデータを右側の処理に流し込みます。
【記述例】
{{ name|upper }}
プログラミングが初めての方でも安心してください。例えば「商品価格に自動で『円』を付ける」「長すぎるタイトルを『...』で省略する」といった、かゆいところに手が届く機能を自分で作れるのがカスタム拡張の魅力です。標準機能に縛られず、あなたのWebサイト専用の便利なショートカットを定義していきましょう。
2. カスタムTwig拡張クラスの作成
Symfonyでは、Twigの拡張機能を作るには、TwigExtensionクラスを作成して、サービスとして登録します。
まず、次のようなクラスを作成してみましょう。
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Twig\TwigFilter;
class AppExtension extends AbstractExtension
{
public function getFunctions(): array
{
return [
new TwigFunction('greeting', [$this, 'greetingFunction']),
];
}
public function getFilters(): array
{
return [
new TwigFilter('reverse', [$this, 'reverseFilter']),
];
}
public function greetingFunction(string $name): string
{
return 'こんにちは、' . $name . 'さん!';
}
public function reverseFilter(string $text): string
{
return strrev($text);
}
}
ここでは、greeting関数と、reverseフィルターの2つを定義しています。これでTwigテンプレート内から使用できるようになります。
3. サービスとして登録しよう(自動登録)
Symfony 4以降では、自動的にTwigにサービスが登録されるため、特別な設定は不要です。ただし、サービスファイルにあるservices.yamlで自動登録が有効になっていることは確認しましょう。
# config/services.yaml
services:
App\Twig\:
resource: '../src/Twig'
tags: ['twig.extension']
これで、Twig内から自作した関数・フィルターが使えるようになります。
4. Twigテンプレートでカスタム関数を使う
では、先ほど作成したgreeting関数をTwigで実際に使ってみましょう。
<p>{{ greeting('太郎') }}</p>
これは「こんにちは、太郎さん!」というメッセージを出力します。独自の挨拶機能など、表示内容を自由に変えたいときに便利です。
5. Twigテンプレートでカスタムフィルターを使う
次に、reverseというフィルターを使って、文字列を逆さに表示する例です。
<p>{{ 'Symfony'|reverse }}</p>
このように書くと、ymonfSのように文字が反転して表示されます。文章や文字列の加工処理を入れたいときに非常に便利です。
6. カスタムTwig機能の活用例
カスタム関数やフィルターを使うことで、次のような場面でTwigテンプレートをより便利にできます。
- 会員名の敬称付け(例:「様」「さん」など)
- 郵便番号や電話番号のフォーマット処理
- 改行文字をHTMLの
<br>に変換 - 特定キーワードのハイライト表示
複雑な処理はPHP側で書いて、Twigではシンプルに表示に集中できるように設計できます。
7. Twigでの命名と注意点
カスタム関数・フィルターを作るときは、次のような点に注意しましょう。
- 関数名・フィルター名はわかりやすく:処理の内容が伝わる名前にすること。
- 変数の型に注意:文字列だけでなく配列などを扱うときは型チェックをしましょう。
- 共通ロジックの再利用:同じ処理が何度もあるならTwig拡張で一元化すると便利です。
まとめ
今回の記事では、PHPのフレームワークであるSymfonyで採用されている強力なテンプレートエンジン「Twig」を自分好みにカスタマイズする方法について詳しく解説してきました。標準で用意されているフィルターや関数だけでも十分に強力ですが、実際のプロジェクト開発では、業務固有の計算ロジックや特定の表示フォーマットが必要になる場面が多々あります。そうした際に、自作のカスタム関数やカスタムフィルターを導入することで、テンプレート側(HTML側)のコードを劇的にスッキリさせ、可読性とメンテナンス性を向上させることができます。
Twig拡張のメリットと設計のコツ
カスタム拡張を導入する最大のメリットは、「ロジックとデザインの分離」を徹底できる点にあります。例えば、複雑なif文や文字列操作をテンプレート内に直接書き込んでしまうと、後からデザインを修正する際にプログラムコードが邪魔になり、ミスを誘発しやすくなります。これをPHPクラス側のメソッドとして定義しておけば、Twig内では「{{ format_id(user.id) }}」のように一行書くだけで済みます。
また、複数のページで同じ表示ルール(日付のフォーマット、金額のカンマ区切り、特定のキーワードのカラーリングなど)を適用する場合も、拡張機能として一つ作っておけば、修正が必要になった際に一箇所を直すだけで全てのページに反映されます。これは大規模なWeb開発において、変更に強いシステムを作るための重要なテクニックです。
さらに高度なカスタム関数の実装例
ここでは、学んだことを応用して、実務でよく使われる「会員ランクに応じたバッジ表示」を生成するような、少し実践的なカスタム関数の例を見てみましょう。
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class UserAppExtension extends AbstractExtension
{
public function getFunctions(): array
{
return [
// HTMLを出力する場合は 'is_safe' オプションが重要です
new TwigFunction('render_rank_badge', [$this, 'renderRankBadge'], ['is_safe' => ['html']]),
];
}
public function renderRankBadge(string $rank): string
{
$color = 'secondary';
$label = '一般会員';
if ($rank === 'gold') {
$color = 'warning';
$label = 'ゴールド会員';
} elseif ($rank === 'premium') {
$color = 'danger';
$label = 'プレミアム会員';
}
// HTMLタグを動的に生成して返す例
return sprintf('<span class="badge bg-%s">%s</span>', $color, $label);
}
}
この関数をTwigテンプレート側で呼び出すときは、以下のようになります。
{# ユーザーのランクが 'gold' の場合 #}
<div class="user-profile">
ユーザー名:{{ user.name }}
ランク:{{ render_rank_badge(user.rank) }}
</div>
実行結果は以下のようになります。
<div class="user-profile">
ユーザー名:山田太郎
ランク:<span class="badge bg-warning">ゴールド会員</span>
</div>
開発時のデバッグと注意点
カスタム機能を実装する際、もし反映されない場合は Symfony のキャッシュが原因であることがあります。開発環境であれば自動で反映されることが多いですが、`bin/console cache:clear` コマンドを実行してキャッシュをクリアする習慣をつけておくと安心です。また、`services.yaml` でのタグ設定(`twig.extension`)が正しく行われているかも、不具合が生じた際のチェックポイントになります。
Twigは非常に自由度が高いツールですが、何でもかんでもカスタム関数にするのではなく、まずは標準のフィルターで対応できないか検討することも大切です。標準機能を使いこなしつつ、どうしても手が届かない痒いところに「カスタム拡張」という強力な武器を差し込むのが、プロのエンジニアへの近道と言えるでしょう。
先生
「さて、Twigのカスタム関数とフィルターの作り方について一通り解説しましたが、イメージは湧きましたか?」
生徒
「はい!思っていたよりもシンプルに作れるんですね。PHP側でロジックを書いて、Twigで呼び出すだけっていう流れが分かりやすかったです。」
先生
「その通りです。特にテンプレートの中に長いif文や、PHPのネイティブ関数を無理やり呼び出すような書き方をしてしまっている時は、カスタム拡張を作る絶好のタイミングですよ。」
生徒
「確かに、HTMLの中に複雑なPHPの理屈が入ってくると、後で見返した時にどこまでがデザインでどこからがプログラムか分からなくなっちゃいますもんね。さっきのバッジを表示する関数みたいに、HTMLを返すこともできるんですか?」
先生
「良いところに気づきましたね。HTMLを直接返す場合は、`'is_safe' => ['html']` というオプションを指定するのがポイントです。これを忘れると、Twigが安全のためにタグをエスケープしてしまって、画面にタグがそのまま文字として出てしまいますから注意してください。」
生徒
「なるほど、セキュリティ(XSS対策)もしっかり考えられているんですね。フィルターと関数の使い分けはどうすればいいですか?」
先生
「基本的には、値を変換・加工して出力するのが目的なら『フィルター』、何か新しい情報を生成したり、引数に基づいて複雑な処理を走らせたりするのが目的なら『関数』と使い分けるのが一般的です。例えば、`|date` のように変数に対して適用するものはフィルターが自然ですね。」
生徒
「スッキリしました!これで読みやすいテンプレートが書けそうです。さっそく今のプロジェクトの郵便番号フォーマットをカスタムフィルターに置き換えてみます!」
先生
「素晴らしいですね。その調子で、保守性の高いコードを目指していきましょう!」