
在构建API驱动的应用程序时,经常需要为前端提供数据筛选功能。例如,一个产品列表可能需要按品牌或产品类型进行筛选。当这些筛选条件(如品牌和产品类型)作为嵌套实体(例如,Product 实体通过 ProductModel 关联到 Brand 和 ProductType)存在时,直接通过API Platform的默认机制获取所有唯一的品牌和产品类型列表会比较复杂。本教程将指导您如何创建一个自定义端点,以返回一个包含所有独特品牌和产品类型的JSON对象,格式如下:
{
"brands": [
"Agilent",
"Comtr",
"Anot"
],
"types": [
"Accelerometer",
"Sonometer",
"Micro-amplifier"
]
}我们将使用API Platform的自定义操作(Custom Operations)功能,结合Symfony控制器和Doctrine实体仓库来完成此任务。
首先,我们需要在相关的实体上定义一个自定义的集合操作(collection operation)。由于品牌(idBrand)和产品类型(idProductType)都直接关联在 ProductModel 实体上,我们将把这个自定义操作添加到 ProductModel 实体对应的 ApiResource 注解中。
打开 App\Entity\ProductModel 类,修改其 ApiResource 注解,添加一个名为 filters 的自定义操作:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\ProductModelRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity(repositoryClass=ProductModelRepository::class)
* @ApiResource(
* itemOperations={"get"},
* collectionOperations={
* "get",
* "filters"={
* "method"="GET",
* "path"="/product_models/filters",
* "controller"=App\Controller\Action\DistinctFiltersAction::class,
* "openapi_context"={
* "summary"="获取所有产品模型中唯一的品牌和产品类型",
* "parameters"={}
* },
* "read"=false, // 表示此操作不用于获取单个资源
* }
* },
* normalizationContext={
* "groups"={"read"}}
* )
*/
class ProductModel
{
// ... 实体属性和方法
}关键点解释:
接下来,我们需要在 ProductModel 对应的仓库(ProductModelRepository)中添加方法,用于从数据库中查询所有独特的品牌名称和产品类型名称。
打开 App\Repository\ProductModelRepository.php,添加以下两个方法:
<?php
namespace App\Repository;
use App\Entity\ProductModel;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method ProductModel|null find($id, $lockMode = null, $lockVersion = null)
* @method ProductModel|null findOneBy(array $criteria, array $orderBy = null)
* @method ProductModel[] findAll()
* @method ProductModel[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ProductModelRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ProductModel::class);
}
/**
* 获取所有独特的品牌名称列表。
* 假设 Brand 实体有一个 'name' 属性。
*
* @return array
*/
public function getDistinctBrands(): array
{
return $this->createQueryBuilder('pm')
->select('b.name') // 选择 Brand 实体的名称属性
->join('pm.idBrand', 'b') // 通过 idBrand 关联到 Brand 实体
->groupBy('b.name') // 按品牌名称分组以获取唯一值
->getQuery()
->getSingleColumnResult(); // 返回一个简单的字符串数组
}
/**
* 获取所有独特的产品类型名称列表。
* 假设 ProductType 实体有一个 'name' 属性。
*
* @return array
*/
public function getDistinctProductTypes(): array
{
return $this->createQueryBuilder('pm')
->select('pt.name') // 选择 ProductType 实体的名称属性
->join('pm.idProductType', 'pt') // 通过 idProductType 关联到 ProductType 实体
->groupBy('pt.name') // 按产品类型名称分组以获取唯一值
->getQuery()
->getSingleColumnResult(); // 返回一个简单的字符串数组
}
}代码说明:
最后,我们需要创建在 ApiResource 注解中指定的控制器类 App\Controller\Action\DistinctFiltersAction。这个控制器将负责调用仓库方法,并将结果格式化成所需的JSON结构。
在 src/Controller/Action/ 目录下创建 DistinctFiltersAction.php 文件(如果 Action 目录不存在,请创建):
<?php
namespace App\Controller\Action;
use App\Repository\ProductModelRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class DistinctFiltersAction
* @Route(
* path="/product_models/filters",
* methods={"GET"},
* defaults={"_api_resource_class"=ProductModel::class, "_api_collection_operation_name"="filters"}
* )
*/
final class DistinctFiltersAction extends AbstractController
{
/**
* 处理获取独特品牌和产品类型列表的请求。
*
* @param ProductModelRepository $productModelRepository
* @return JsonResponse
*/
public function __invoke(ProductModelRepository $productModelRepository): JsonResponse
{
// 调用仓库方法获取独特的品牌和产品类型
$brands = $productModelRepository->getDistinctBrands();
$types = $productModelRepository->getDistinctProductTypes();
// 将结果格式化为所需的JSON结构并返回
return new JsonResponse([
'brands' => $brands,
'types' => $types,
]);
}
}代码说明:
注意事项:
完成以上步骤后,您可以通过以下方式验证您的自定义端点:
composer dump-autoload php bin/console cache:clear
php bin/console debug:router
您应该能看到类似 /product_models/filters 的路由。
通过结合API Platform的自定义操作、Doctrine实体仓库的强大查询能力以及Symfony控制器的灵活性,我们成功地为嵌套实体创建了一个高效且结构化的筛选器数据端点。这种方法不仅满足了前端对独特数据列表的需求,也保持了API的整洁和专业性。在实际项目中,您可以根据需要扩展这些仓库方法,例如添加分页、排序或更复杂的筛选逻辑,以适应不断变化的业务需求。
以上就是在API Platform中为嵌套实体创建自定义筛选器端点的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号