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

如何使用API Platform与Gedmo Translatable查询可翻译属性

解决Gedmo Translatable字段在API Platform中无法搜索的问题

核心问题

默认SearchFilter仅查询主实体字段,而Gedmo翻译字段存储在关联的翻译表(如foo_translations)中,需自定义查询逻辑关联翻译表才能实现搜索。

解决方案步骤

1. 创建自定义Doctrine查询扩展

这个扩展会在查询集合时自动关联翻译表,并根据请求参数过滤对应语言的翻译内容:

// src/Doctrine/Extension/TranslatableSearchExtension.php
namespace App\Doctrine\Extension;

use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use App\Entity\Foo;
use Doctrine\ORM\QueryBuilder;
use Gedmo\Translatable\TranslatableListener;
use Symfony\Component\HttpFoundation\RequestStack;

class TranslatableSearchExtension implements QueryCollectionExtensionInterface
{
    public function __construct(
        private readonly RequestStack $requestStack,
        private readonly TranslatableListener $translatableListener
    ) {}

    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
    {
        if ($resourceClass !== Foo::class) {
            return;
        }

        $request = $this->requestStack->getCurrentRequest();
        if (!$request || !$request->query->has('name')) {
            return;
        }

        $locale = $request->query->get('_locale', $this->translatableListener->getDefaultLocale());
        $searchTerm = $request->query->get('name');

        $rootAlias = $queryBuilder->getRootAliases()[0];
        $translationAlias = $queryNameGenerator->generateJoinAlias('translation');

        $queryBuilder
            ->leftJoin(sprintf('%s.translations', $rootAlias), $translationAlias)
            ->andWhere(sprintf('%s.locale = :locale', $translationAlias))
            ->andWhere(sprintf('%s.field = :field', $translationAlias))
            ->andWhere(sprintf('%s.content LIKE :searchTerm', $translationAlias))
            ->setParameter('locale', $locale)
            ->setParameter('field', 'name')
            ->setParameter('searchTerm', "%{$searchTerm}%");
    }
}

2. 注册查询扩展

在services.yaml中添加服务标签,让API Platform识别这个扩展:

services:
    App\Doctrine\Extension\TranslatableSearchExtension:
        tags:
            - { name: api_platform.doctrine.orm.query_extension.collection }

3. 调整实体的SearchFilter配置

移除实体上name字段的默认SearchFilter配置,避免逻辑冲突:

#[ApiFilter(SearchFilter::class, properties: [
    // 移除原有的'name' => 'partial'配置
])]

4. 测试搜索请求

使用以下格式发起请求,_locale参数可选,默认会使用系统默认语言:

GET https://localhost/api/foos?name=bar&_locale=en

补充说明

  • 若需支持多语言搜索(匹配任意语言下的翻译内容),可移除locale条件,但建议为翻译表的field和content字段添加联合索引优化性能。
  • 如需支持多个可翻译字段搜索,可扩展上述逻辑,遍历请求中的查询参数,匹配对应的翻译字段。

内容的提问来源于stack exchange,提问作者RedBeard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:24:55