如何使用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
相关产品推荐
相关产品推荐

