You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否有Symfony友好的方法去除字符串中的所有Twig标签?

Symfony验证约束:用服务替代正则去除Twig标签

你当前用正则去除Twig标签后统计字符长度的方法虽然可行,但确实存在健壮性问题(比如无法处理嵌套标签、特殊字符场景)。完全可以通过注入服务的方式来处理,这更符合Symfony的服务化架构风格,也更可靠。

实现步骤

1. 创建Twig标签清理服务

基于Twig官方的Lexer来解析模板内容,精准区分Twig标签和普通文本,避免正则的局限性:

namespace App\Service;

use Twig\Lexer;
use Twig\Token;

class TwigTagCleaner
{
    private Lexer $lexer;

    public function __construct(Lexer $lexer)
    {
        $this->lexer = $lexer;
    }

    public function clean(string $content): string
    {
        $tokens = $this->lexer->tokenize($content);
        $cleanedContent = '';

        foreach ($tokens as $token) {
            // 保留普通文本
            if ($token->getType() === Token::TEXT_TYPE) {
                $cleanedContent .= $token->getValue();
            }
            // 跳过Twig标签的标记(可根据需求调整是否保留变量内容)
            if ($token->getType() === Token::VAR_START_TYPE || $token->getType() === Token::VAR_END_TYPE || $token->getType() === Token::BLOCK_START_TYPE || $token->getType() === Token::BLOCK_END_TYPE) {
                continue;
            }
        }

        return $cleanedContent;
    }
}

2. 实现支持依赖注入的验证约束

在Symfony 6.2+版本中,使用#[AsValidator]属性让验证器自动支持依赖注入,注入上面创建的清理服务:

验证器类

namespace App\Validator;

use App\Service\TwigTagCleaner;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

#[AsValidator]
class MaxLengthWithoutTwigTagsValidator extends ConstraintValidator
{
    private TwigTagCleaner $tagCleaner;

    public function __construct(TwigTagCleaner $tagCleaner)
    {
        $this->tagCleaner = $tagCleaner;
    }

    public function validate($value, Constraint $constraint)
    {
        if (!$constraint instanceof MaxLengthWithoutTwigTags) {
            throw new UnexpectedTypeException($constraint, MaxLengthWithoutTwigTags::class);
        }

        if (null === $value || '' === $value) {
            return;
        }

        if (!is_string($value)) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $cleanedContent = $this->tagCleaner->clean($value);
        $parsedLength = mb_strlen($cleanedContent);

        if ($parsedLength > $constraint->max) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('{{ limit }}', $constraint->max)
                ->setParameter('{{ current }}', $parsedLength)
                ->addViolation();
        }
    }
}

约束类

namespace App\Validator;

use Symfony\Component\Validator\Constraint;

#[Attribute]
class MaxLengthWithoutTwigTags extends Constraint
{
    public string $message = '该字段去除Twig标签后长度不能超过{{ limit }}字符,当前为{{ current }}字符。';
    public int $max;

    public function __construct(int $max, ?string $message = null, array $groups = null, mixed $payload = null)
    {
        parent::__construct($groups, $payload);
        $this->max = $max;
        $this->message = $message ?? $this->message;
    }
}

3. 在字段上使用约束

直接在实体或DTO的字段上标注自定义约束即可:

use App\Validator\MaxLengthWithoutTwigTags;

class YourContentEntity
{
    #[MaxLengthWithoutTwigTags(max: 200)]
    private string $content;

    // 对应的getter、setter方法
}

为什么这种方式更优

  • 更可靠:基于Twig官方的解析器处理标签,能覆盖所有Twig语法场景(嵌套标签、特殊字符等),不会出现正则匹配遗漏的问题
  • 解耦复用:标签清理逻辑封装成独立服务,可在其他业务场景中复用
  • 易维护:后续Twig语法更新时,无需手动调整正则表达式,直接依赖Twig官方组件即可

内容的提问来源于stack exchange,提问作者Mayor of the Plattenbaus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:12:37