如何扩展Hydra搜索上下文以在客户端生成筛选字段?
解决方案
方法1:自定义筛选器扩展元数据
创建自定义筛选器子类,在其中为特定字段添加自定义元数据,这些元数据会被Hydra纳入响应中:
use ApiPlatform\Doctrine\Orm\Filter\DateFilter; class CustomDateFilter extends DateFilter { public function getDescription(string $resourceClass): array { $description = parent::getDescription($resourceClass); // 为不同字段标记自定义类型 foreach ($description as $key => &$data) { if (str_starts_with($key, 'createdAt')) { $data['custom_type'] = 'range_date_picker'; } elseif (str_starts_with($key, 'birthdate')) { $data['custom_type'] = 'single_date_picker'; } } return $description; } }
在实体中替换原筛选器使用自定义版本:
class Entity { #[ApiFilter(CustomDateFilter::class, properties: ['createdAt'])] protected ?DateTimeInterface $createdAt = null; #[ApiFilter(CustomDateFilter::class, properties: ['birthdate'])] protected ?DateTimeInterface $birthdate = null; }
方法2:通过自定义序列化器注入上下文信息
- 在
ApiResource的操作中定义自定义Hydra上下文:
#[ApiResource( operations: [ new GetCollection( hydraContext: [ 'filter_metadata' => [ 'createdAt' => ['type' => 'range_date_picker'], 'birthdate' => ['type' => 'single_date_picker'] ] ] ) ] )]
- 创建自定义序列化器,将上下文信息注入到Hydra的搜索元数据中:
use ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer; use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; class CustomHydraCollectionFiltersNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface { use NormalizerAwareTrait; public function normalize($object, string $format = null, array $context = []): array { $data = $this->normalizer->normalize($object, $format, $context); // 从操作上下文取自定义元数据,追加到hydra:mapping中 if (isset($context['operation']?->getHydraContext()['filter_metadata'])) { $filterMetadata = $context['operation']->getHydraContext()['filter_metadata']; foreach ($data['hydra:search']['hydra:mapping'] as &$mapping) { $property = $mapping['property']; if (isset($filterMetadata[$property])) { $mapping['custom_metadata'] = $filterMetadata[$property]; } } } return $data; } public function supportsNormalization($data, string $format = null, array $context = []): bool { return $this->normalizer instanceof ContextAwareNormalizerInterface && $this->normalizer->supportsNormalization($data, $format, $context); } }
- 在
services.yaml注册该序列化器,确保优先级高于默认的集合筛选器归一化器:
services: App\Serializer\CustomHydraCollectionFiltersNormalizer: tags: - { name: serializer.normalizer, priority: 100 }
方法3:扩展Hydra元数据生成器
若需全局生效的自定义元数据,可扩展ApiPlatform\Hydra\Serializer\HydraSerializer或ApiPlatform\Metadata\Resource\Factory\ResourceMetadataFactoryInterface,在元数据生成阶段直接插入自定义字段。
内容的提问来源于stack exchange,提问作者Stephan Vierkant
相关产品推荐
相关产品推荐

