Я использую 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"
Я иду по неверному пути? Я что-то пропустил?
Когда я не пытаюсь сериализовать отфильтрованную коллекцию, но оригинальную, она работает, но я получаю все сущности.
Вы должны использовать пользовательские фильтры API Platform вместо прослушивателя Doctrine: https://api-platform.com/docs/core/filters#creating-custom-filters
Это будет легче реализовать и быстрее выполнить (данные будут отфильтрованы на стороне СУБД, а не на стороне PHP).
Других решений пока нет …