Twigのnl2brでtableやdivに余計なbrが入る問題を防ぐ方法
EC-CUBEのテンプレートで {{ Product.description_detail|raw|nl2br }} を使用すると、<table> や <div> の内部にも <br> が挿入されてしまう問題が発生することがあります。これは、nl2br フィルターがHTMLタグの構造を考慮せずに適用されるためです。
目次
1. 解決策:カスタムフィルター safe_nl2br を作成
この問題を解決するために、Twig のカスタムフィルター safe_nl2br を作成し、nl2br を適用する範囲を制御します。さらに、サービスの登録を NoBrFilterExtension.php 内で完結させ、設定の手間を省きます。
2. safe_nl2br を作成 するNoBrFilterExtension.php を設置
ファイルパス
app/Customize/Twig/Extension/NoBrFilterExtension.php
コード
<?php
namespace Customize\Twig\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class NoBrFilterExtension extends AbstractExtension
{
public function getFilters()
{
return [
new TwigFilter('safe_nl2br', [$this, 'safeNl2br'], ['is_safe' => ['html']]),
];
}
public function safeNl2br($string)
{
// <table>, <div> などのブロック要素を一時的にプレースホルダーに置き換え
$placeholders = [];
$string = preg_replace_callback('/(<table.*?>.*?<\/table>|<div.*?>.*?<\/div>)/is', function ($matches) use (&$placeholders) {
$key = '__PLACEHOLDER_' . count($placeholders) . '__';
$placeholders[$key] = $matches[0];
return $key;
}, $string);
// nl2br を適用
$string = nl2br($string);
// プレースホルダーを元のタグに戻す
return str_replace(array_keys($placeholders), array_values($placeholders), $string);
}
}
// 自動的にサービスを登録するための Bundle クラス
class NoBrFilterBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
$container->register(NoBrFilterExtension::class)
->addTag('twig.extension');
}
}
3. Twig テンプレートでの使用方法
作成した safe_nl2br フィルターを使用することで、<table> や <div> 内に <br> が挿入される問題を防ぐことができます。
{{ Product.description_detail|raw|safe_nl2br }}