API 平台 - 如何创建自定义集合操作 (GET)?

API Platform - How to create a custom collection operation (GET)?

我从 API 平台开始,我必须重构一个没有使用 API 平台的旧 API。我正在使用 Symfony 5 和 Doctrine,我公开了带有注释 @Api 平台的实体,我在 API 文档上看到了 CRUD 操作。但是我要自定义几个操作,遇到了一些困难。

首先,我想按特定属性获取项目集合。

实体:

/**
 * Parcsportif
 * @ApiResource(
 * collectionOperations={"get"},
 * itemOperations={"get"})
 *
 * @ORM\Table(name="parcSportif", indexes={@ORM\Index(name="index_numSite", columns={"numSite"})})
 * @ORM\Entity
 */
class Parcsportif
{
    /**
     * @var int
     * @ORM\Column(name="numParc", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $numparc;

    /**
     * @var int
     * @ORM\Column(name="numSite", type="integer", nullable=false)
     */
    private $numsite = '0';

    // others attributes and getters and setters


Api平台生成的路由是:

但我想这样修改它们:

  1. /api/listeEquipements/{numsite} : 通过 'numsite' 属性获取集合
  2. /api/informationEquipement/{numparc} : 获取项目

所以我像这样更改了实体:

**
 * Parcsportif
 * @ApiResource(
 *      collectionOperations={
 *     "get"={
 *                  "method"="GET",
 *                  "path"="/listeEquipementsClient/{numsite}",
 *                  "openapi_context" = {
 *                      "parameters" = {
 *                          {
 *                              "name" = "numsite",
 *                              "in" = "path",
 *                              "description" = "numéro site",
 *                              "required" = true,
 *                              "schema"={
 *                                  "type" : "integer"
 *                              },
 *                              "style"="simple"
 *                          }
 *                      }
 *            },
 *              "controller" = ListeEquipementsController::class
 *       }
 *     },
 *     itemOperations={"get"={"path"="/informationEquipement/{numparc}"}}
 * )

上面的控制器是:

class ListeEquipementsController
{
    private $parcSportifRepository;

    public function __construct(ParcSportifRepository $parcSportifRepository)
    {
        $this->parcSportifRepository = $parcSportifRepository;
    }

    public function __invoke($numsite): iterable
    {
        return $this->parcSportifRepository->getListeEquipementsParNumSite($numsite);
    }
}

以及实体的存储库:

class ParcSportifRepository extends ServiceEntityRepository
{
    private $em;

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Parcsportif::class);
        $this->em = $this->getEntityManager();
    }

    public function getListeEquipementsParNumSite($numSite): iterable
    {
        return $this->findBy([
            "numsite" => $numSite,
        ]);
    }
}

因此路线 2) 操作“GET item”工作正常,但是当我在 Postman 上调用路线 1) 时出现以下错误:

"Unable to generate an IRI for "App\Entity\Parcsportif"."

没看懂

我怎样才能找到问题所在?

当指定 /listeEquipementsClient/{numsite} 作为路径时,您是在告诉 API 平台 numsite 是您资源的 identifiernumsite 不仅不是资源标识符(这是 numparc,导致您遇到的错误),集合 GET 操作不应该期望 url 路径段塞 作为过滤器参数,而是期望查询参数:

/parcsportifs?numsite=123

这应该为 numsite 值为 123 的资源过滤 Parcsportif 集合,并且可以通过向 [=20] 提供 @ApiFilter 注释来实现=] 属性:

/**
 * @var int
 * @ORM\Column(name="numSite", type="integer", nullable=false)
 * @ApiFilter(
 *      SearchFilter::class,
 *      properties={
 *          "numsite": "exact"
 *      }
 * )
 */
 private $numsite = '0';

如果您真的想实现 post 中描述的端点(使用 numsite 作为资源标识符),您将必须实现自定义资源和 data provider 支持 numsite 作为此资源的标识符。