Пользовательская отфильтрованная коллекция API-платформы как свойство

Я использую api-платформу (https://api-platform.com/) Основа для моего веб-сайта, и я пытаюсь сериализовать коллекцию сущностей несколько раз по разным критериям. Я создал следующие примеры сущностей:

EntityWithFilteredCollection

namespace AppBundle\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

/**
* @ApiResource(attributes={"normalization_context"={"groups"={"get"}}})
* @ORM\Entity()
*/
class EntityWithFilteredCollection
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
* @Groups({"get"})
*/
private $id;

/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\FilteredCollectionRelatedEntity", mappedBy="relatedEntity")
*/
private $relatedEntities;

/**
* @Groups({"get"})
*/
private $filteredEntities;

public function __construct()
{
$this->relatedEntities = new ArrayCollection();
}

public function getId()
{
return $this->id;
}

public function getRelatedEntities()
{
return $this->relatedEntities;
}

public function setRelatedEntities($relatedEntities)
{
$this->relatedEntities = $relatedEntities;
}

public function getFilteredEntities()
{
return $this->filteredEntities;
}

public function setFilteredEntities($filteredEntities)
{
$this->filteredEntities = $filteredEntities;
}
}

FilteredCollectionRelatedEntity

namespace AppBundle\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
* @ApiResource(attributes={"normalization_context"={"groups"={"get"}}})
* @ORM\Entity()
*/
class FilteredCollectionRelatedEntity
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
* @Groups({"get"})
*/
private $id;

/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\RelatedEntity", inversedBy="relatedEntites")
*/
protected $relatedEntity;

/**
* @ORM\Column(type="integer")
* @Groups({"get"})
*/
protected $value;

/**
* @ORM\Column(type="boolean")
* @Groups({"get"})
*/
protected $condition;

public function getId()
{
return $this->id;
}

public function getRelatedEntity()
{
return $this->relatedEntity;
}

public function setRelatedEntity($relatedEntity)
{
$this->relatedEntity = $relatedEntity;
}

public function getValue()
{
return $this->value;
}

public function setValue($value)
{
$this->value = $value;
}

public function getCondition()
{
return $this->condition;
}

public function setCondition($condition)
{
$this->condition = $condition;
}
}

И подписчик на событие Doctrine Post Load Event:

namespace AppBundle\EventSubscriber;use AppBundle\Entity\EntityWithFilteredCollection;
use AppBundle\Entity\FilteredCollectionRelatedEntity;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

class FilterCollectionSubscriber implements EventSubscriber
{
/** @var  RequestStack */
private $requestStack;

public function __construct(TokenStorage $tokenStorage, RequestStack $requestStack)
{
$this->tokenStorage = $tokenStorage;
$this->requestStack = $requestStack;
}public function postLoad(LifecycleEventArgs $event)
{
$entity = $event->getEntity();
$method = $this->requestStack->getCurrentRequest()->getMethod();if (!$entity instanceof EntityWithFilteredCollection || Request::METHOD_GET !== $method) {
return;
}

$entity->setFilteredEntities($entity->getRelatedEntities()->filter(function (FilteredCollectionRelatedEntity $entity) {
return $entity->getCondition();
}));

}

/**
* Returns an array of events this subscriber wants to listen to.
*
* @return array
*/
public function getSubscribedEvents()
{
return [
'postLoad'
];
}
}

Когда я пытаюсь получить одну коллекцию EntityWithFilteredCollection, в которой есть несколько сущностей FilteredCollectionRelatedEntity, для которых значение условия установлено в значение true, я получаю следующее исключение:

No resource class found for object of type "AppBundle\Entity\FilteredCollectionRelatedEntity"

Я иду по неверному пути? Я что-то пропустил?
Когда я не пытаюсь сериализовать отфильтрованную коллекцию, но оригинальную, она работает, но я получаю все сущности.

1

Решение

Вы должны использовать пользовательские фильтры API Platform вместо прослушивателя Doctrine: https://api-platform.com/docs/core/filters#creating-custom-filters

Это будет легче реализовать и быстрее выполнить (данные будут отфильтрованы на стороне СУБД, а не на стороне PHP).

0

Другие решения

Других решений пока нет …