I'm new with Api-platform 2.6 and i kind of succeeded to do what i attempted but i don't know if it's the "right" or easiest way to do it.
Here's what i'm trying to do:
i got an esirius_site entity that that have a collection of visitors.
The visitors are not stored in the database but they are fetched from an api endpoint.
I want to have a route like : /esirius_sites/{idsys}/visitors
that return a collection of visitors (see result bellow). I don't want the route to return a esirius_site
i succeeded to do it by setting the visitors as a sub-resource:
<?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;
}
}
and then i created a Data provider to fetch the visitor collection :
<?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();
}
}
In this data provider i use the SubresourceDataProviderInterface
(i found it randomly) that's not mentioned in the api platform documentation.
I finally got the result that i espect:
{
"@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
}