获取实体所有子资源的自定义路径
custom path to get all the subressource of an entity
我是 Api-platform 2.6 的新手,我有点成功地完成了我尝试的事情,但我不知道这是不是“正确”或最简单的方法。
这是我正在尝试做的事情:
我得到了一个 esirius_site 实体,其中包含访问者集合。
访问者未存储在数据库中,而是从 api 端点获取。
我想要一条像这样的路线:/esirius_sites/{idsys}/visitors
那 return 一组访客(见下面的结果)。我不想要通往 return a esirius_site
的路线
我通过将访问者设置为子资源成功地做到了:
<?php
/**
* @ORM\Entity(repositoryClass=EsiriusSiteRepository::class)
* @ApiResource(
* collectionOperations={
* },
* itemOperations={
* "get",
*
* }
* )
*/
class EsiriusSite
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
private $idsys;
/** Other properties... **/
/**
* @ApiSubresource()
*/
private $visitors;
public function __construct()
{
$this->visitors = [];
}
public function getIdsys(): ?int
{
return $this->idsys;
}
/**
* @return array
*/
public function getVisitors():array
{
return $this->visitors;
}
public function addVisitor(Visitor $visitor): self
{
$this->visitors[]=$visitor;
$visitor->setEsiriusSite($this);
return $this;
}
}
然后我创建了一个数据提供程序来获取访问者集合:
<?php
namespace App\DataProvider;
class VisitorItemDataProvider implements SubresourceDataProviderInterface,RestrictedDataProviderInterface
{
private EsiriusVisitorWebService $visitorWebService;
private EsiriusSiteRepository $siteRepository;
public function __construct(EsiriusVisitorWebService $visitorWebService, EsiriusSiteRepository $siteRepository)
{
$this->visitorWebService = $visitorWebService;
$this->siteRepository = $siteRepository;
}
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return $resourceClass === Visitor::class;
}
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
{
$site = $this->siteRepository->find($identifiers["idsys"]["idsys"]);
$esiriusVisitors = ($this->visitorWebService->getVisitors([$site->getCode()]))->visitorArray;
if($esiriusVisitors== new \stdClass())
return [];
foreach ($esiriusVisitors as $visitor) {
$newVisitor = (new Visitor())->setFirstName($visitor->firstName)->setLastname($visitor->name)->setId($visitor->businessIdentity);
$site->addVisitor($newVisitor);
}
return $site->getVisitors();
}
}
在这个数据提供者中,我使用 SubresourceDataProviderInterface
(我随机发现的)api 平台文档中没有提到。
我终于得到了我期待的结果:
{
"@context": "/q0met-api/contexts/Visitor",
"@id": "/q0met-api/esirius_sites/18/visitors",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/q0met-api/visitors/1234",
"@type": "Visitor",
"id": "1234",
"firstName": "Jean",
"lastname": "Michel",
"esiriusSite": "/q0met-api/esirius_sites/18"
}
],
"hydra:totalItems": 1
}
我做得对吗?有没有更好的方法可以不使用这个未记录的界面?
@soyuka 证实,我的解决方案很好
我是 Api-platform 2.6 的新手,我有点成功地完成了我尝试的事情,但我不知道这是不是“正确”或最简单的方法。
这是我正在尝试做的事情:
我得到了一个 esirius_site 实体,其中包含访问者集合。
访问者未存储在数据库中,而是从 api 端点获取。
我想要一条像这样的路线:/esirius_sites/{idsys}/visitors
那 return 一组访客(见下面的结果)。我不想要通往 return a esirius_site
我通过将访问者设置为子资源成功地做到了:
<?php
/**
* @ORM\Entity(repositoryClass=EsiriusSiteRepository::class)
* @ApiResource(
* collectionOperations={
* },
* itemOperations={
* "get",
*
* }
* )
*/
class EsiriusSite
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
private $idsys;
/** Other properties... **/
/**
* @ApiSubresource()
*/
private $visitors;
public function __construct()
{
$this->visitors = [];
}
public function getIdsys(): ?int
{
return $this->idsys;
}
/**
* @return array
*/
public function getVisitors():array
{
return $this->visitors;
}
public function addVisitor(Visitor $visitor): self
{
$this->visitors[]=$visitor;
$visitor->setEsiriusSite($this);
return $this;
}
}
然后我创建了一个数据提供程序来获取访问者集合:
<?php
namespace App\DataProvider;
class VisitorItemDataProvider implements SubresourceDataProviderInterface,RestrictedDataProviderInterface
{
private EsiriusVisitorWebService $visitorWebService;
private EsiriusSiteRepository $siteRepository;
public function __construct(EsiriusVisitorWebService $visitorWebService, EsiriusSiteRepository $siteRepository)
{
$this->visitorWebService = $visitorWebService;
$this->siteRepository = $siteRepository;
}
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return $resourceClass === Visitor::class;
}
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
{
$site = $this->siteRepository->find($identifiers["idsys"]["idsys"]);
$esiriusVisitors = ($this->visitorWebService->getVisitors([$site->getCode()]))->visitorArray;
if($esiriusVisitors== new \stdClass())
return [];
foreach ($esiriusVisitors as $visitor) {
$newVisitor = (new Visitor())->setFirstName($visitor->firstName)->setLastname($visitor->name)->setId($visitor->businessIdentity);
$site->addVisitor($newVisitor);
}
return $site->getVisitors();
}
}
在这个数据提供者中,我使用 SubresourceDataProviderInterface
(我随机发现的)api 平台文档中没有提到。
我终于得到了我期待的结果:
{
"@context": "/q0met-api/contexts/Visitor",
"@id": "/q0met-api/esirius_sites/18/visitors",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/q0met-api/visitors/1234",
"@type": "Visitor",
"id": "1234",
"firstName": "Jean",
"lastname": "Michel",
"esiriusSite": "/q0met-api/esirius_sites/18"
}
],
"hydra:totalItems": 1
}
我做得对吗?有没有更好的方法可以不使用这个未记录的界面?
@soyuka 证实,我的解决方案很好