LoginSignup
2
3

More than 1 year has passed since last update.

HTMLテンプレートを扱う、"Twig Bundle"

Last updated at Posted at 2022-12-08

Symfony Component Advent Calendar 2022の9日目の記事です。

最初に

SymfonyはPHPのフレームワークのひとつです。しかし、公式サイトの説明文には

Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
(SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。)

と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。

今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。

※記事内ではautoloadのインポートは省略します。

HTMLテンプレートを扱う、"Twig Bundle"

Twig Bundleは、SymfonyでHTMLのテンプレートであるTwigを扱えるようにするコンポーネントです。

インストール

composer require symfony/twig-bundle

Twigの基本

Twigの基本的な使い方は{{ ... }}, {% ... %}という文法を使ってアプリケーションから渡された値を出力したり、制御したりして使います。

ItemController.php
public function index(ItemRepository $itemRepository): Response
{
    $items = $itemRepository->findAll();
    
    return $this->render('index.html.twig', [
        'name' => 'すみだ',
        'items' => $items,
    ]);
}
index.html.twig

<div>
こんにちは、{{ name }}さん。
</div>

<ul>
{% for item in items %}
<li>{{ item.name }} {{ item.price|number_format }}</li>
{% endfor %}
</ul>

{{ ... }}で、アプリケーション(上記の例ではController)から渡されたキーに紐づく値やTwig関数の実行結果を出力します。Twig側は$が必要ありません。
{% ... %}で、Twig上で使えるTwigタグを実行します。上記の例では繰り返し処理を行う{% for %}, {% endfor %}を使って、商品リストを出力しています。
また、出力時に|移行にTwigフィルターを使って値を加工することもできます。

詳しくはこちら

Twigの特徴

Twigは他のフレームワークで利用しているテンプレートエンジンと同じく、HTMLのテンプレートを使って、HTMLを出力することができますが、他のものとはちょっと違う特徴があります。そのうちの一つで、個人的にとても気に入ってるのがテンプレート内でPHPプログラムが動かせないという点です。

例えばLaravelのBladeだと、

index.blade.php
@php

$now = Carbon::now()->format('Y-m-d H:i:s');

@endphp

<span>{{ $now }}</span>

と、テンプレート内でPHPを実行することができます。ところが、Twigにはこのような記述をすることができません。公式ドキュメントにも冒頭で、

You can't run PHP code inside Twig templates,

と記述してあります。

独自フィルター・関数を作る、"TwigExtension"

Twigには豊富なフィルターや関数がすでに用意されていますが、アプリケーション独自のフィルター・関数を作りたい時があります。そんな時はTwigExtensionを作成することで、解決します。

src/Twig/AppExtension.php

namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

class AppExtension extends AbstractExtension
{
    public function __construct(private readonly float $taxRate)
    {
    }

    public function getFilters()
    {
        return [
            new TwigFilter('withTax', [$this, 'formatPrice']),
        ];
    }
    
    public function getFunctions()
    {
        return new TwigFunction('tax', [$this, 'getTax']);
    }

    public function formatPrice(int $price): string
    {
        $priceWithTax = floor($price + ($price * $this->taxRate));

        return number_format($priceWithTax);
    }
    
    public function getTax(int $price): int
    {
        return $price * $this->taxRate;
    }
}

AbstractExtensionの子クラスを作り、getFilters()new TwigFilter('フィルター名', [$this, '実行するメソッド名'])を指定することでフィルターを追加、'getFunctions()'にnew TwigFunction('関数名', [$this, '実行するメソッド名'])を指定することで関数を追加できます。上記の例は消費税を含めた金額に変換するフィルターと、消費税額を返す関数を用意しました。
ここでも当然DIできるので、消費税率はDIしています。

使い方は、通常のTwigフィルター・関数と同様です。

index.html.twig

<div>
こんにちは、{{ name }}さん。
</div>

<ul>
{% for item in items %}
<li>{{ item.name }} {{ item.price|withTax }}円 (うち消費税{{ tax(item.price)|number_format }}円)</li>
{% endfor %}
</ul>

まとめ

今回はTwig Bundleを紹介しました。TwigはViewの出力に専念できるので、とても好きなテンプレートエンジンです。
これもとてもおすすめなので、ぜひ使っていただけたらです。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3