Help us understand the problem. What is going on with this article?

Twigで開発していた困ったところまとめ

More than 1 year has passed since last update.

最近、フレームワークを使っていない環境で、Twigを使う機会があったのですが、
わからない事も多く、その上日本語の解説ページがなくて詰まる場面がありました。

そのため、自分への備忘録も兼ねて、記事にまとめておきたいと思います。

共通テンプレートを読み込み時のパス指定

共通テンプレートを作成して、別画面で読み込み時は{% include 'テンプレート名' %}を使うのですが、
テンプレート名に以下のような相対パスや絶対パスを指定するとエラーになってしまいます。

エラーになる例
{% include '/path/to/common_templates/sample.twig' %}

正しく読み込むには、Twigの組み込みローダーを呼び出した後に、
addPathに共通テンプレートのパスを渡す必要があります。

呼び出し元PHP
$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
    'cache' => '/path/to/compilation_cache',
));
$twig->addPath(/path/to/common_templates/);
画面
{% include 'sample.twig' %}

addPathの第2引数に名前空間も指定する事ができます。

呼び出し元PHP
$twig->addPath(/path/to/common_templates/, 'common_templates');
画面
{% include '@common_templates/sample.twig' %}

配列のキー名を動的に生成して値を取得する

以下のようなキー名に数字の連番が含まれる配列データを、
画面にrenderしていて、その配列の値を、キー値を動的に生成して取得したい場合、
以下のようにすれば取得ができます。

呼び出し元PHP
$data = [
  'sample_1' => '1',
  'sample_2' => '2',
  'sample_3' => '3',
];

$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
    'cache' => '/path/to/compilation_cache',
));
$twig->render('sample.html', $data);

sample.html
<select name="sample_select">
   {% for index in 1..data|length %}
      {% set data_index = "sample_" ~ index %}
      <option value="{{attribute(data, data_index)}}">{{attribute(data, data_index)}}</option>
   {% endfor %}
</select>

自作フィルターを読み込み

Twigで用意されているフィルターではなく、自作フィルターを読み込みたい場合、
Twigの組み込みローダーを呼び出した後に、Twig_Filterクラスにフィルター名と
実行したファンクションを引数に渡してあげて、生成されたオブジェクトをaddFilterに渡してあげる必要があります。

呼び出し元PHP
$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
    'cache' => '/path/to/compilation_cache',
));
$filter = new Twig_Filter('フィルター名', 'ファンクション');
$twig->addFilter($filter);

画面側では通常のフィルターと同じ使い方が出来るようになります。

画面
{{処理したいデータ|フィルター名}}

また、Twig_Filterクラスの引数にはクラスを指定することもできます。

クラスを指定する場合
$filter = new Twig_Filter('フィルター名', ['クラスオブジェクト', 'ファンクション']);

私が開発した環境では自作フィルター用のクラスを作成して、
そのクラスからフィルターを読み込むようにしました。

CustomFilter.class.php
<?php

class CustomFilter
{
   private $customFilterList = [
       'customFilter' => 'customFunction',
   ];

    public function getCustomFilterList(): array
    {
        return $this->customFilterList;
    }

   public function customFunction(string $string): string
   {
       $result = $string . 'CustomFilter';
       return $result;
   }
}
呼び出し元PHP
$cosutomFilter = new CustomFilter();
$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
    'cache' => '/path/to/compilation_cache',
));

$cosutomFilterList = $cosutomFilter->getCustomFilterList();
foreach ($cosutomFilterList as $filterName => $functionName) {
      $filter = new Twig_Filter($filterName, [$cosutomFilter, $functionName]);
      $this->twig->addFilter($filter);
}
画面
{{処理したいデータ|customFilter}}

まとめ

今後もTwigを使っていくと思うので、
この備忘録を更新していけたらと思います。

Twigを使いはじめて日が浅いので、
間違いや、こうしたほうが良いんじゃないかといった意見がありましたら、
ご指摘していただけましたら嬉しいです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away