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平台生成的路由是:
- /api/parcsportifs : 获取集合
- /api/parcsportifs/{numparc} : 获取项目
但我想这样修改它们:
- /api/listeEquipements/{numsite} : 通过 'numsite' 属性获取集合
- /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
是您资源的 identifier。 numsite
不仅不是资源标识符(这是 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
作为此资源的标识符。
我从 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平台生成的路由是:
- /api/parcsportifs : 获取集合
- /api/parcsportifs/{numparc} : 获取项目
但我想这样修改它们:
- /api/listeEquipements/{numsite} : 通过 'numsite' 属性获取集合
- /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
是您资源的 identifier。 numsite
不仅不是资源标识符(这是 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
作为此资源的标识符。