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の基本的な使い方は{{ ... }}
, {% ... %}
という文法を使ってアプリケーションから渡された値を出力したり、制御したりして使います。
public function index(ItemRepository $itemRepository): Response
{
$items = $itemRepository->findAll();
return $this->render('index.html.twig', [
'name' => 'すみだ',
'items' => $items,
]);
}
<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だと、
@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
を作成することで、解決します。
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フィルター・関数と同様です。
<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の出力に専念できるので、とても好きなテンプレートエンジンです。
これもとてもおすすめなので、ぜひ使っていただけたらです。