Здравствуйте.
В проекте используются symfony 2, doctrine.
Есть задача сделать общий рейтинг для различных типов entity через одну общую сущность vote.
Упрощено мы видим ее так:
/**
* Flavi\AppBundle\Entity\Vote
*
* @ORM\Table(name="votes")
* @ORM\Entity(repositoryClass="Flavi\AppBundle\Entity\VoteRepository")
* @ORM\HasLifecycleCallbacks()
* @JMS\ExclusionPolicy("none")
*/
class Vote {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="integer")
*/
protected $userId;
/**
* @ORM\Column(type="integer")
*/
protected $entityId;
/**
* @ORM\Column(type="string")
*/
protected $entity;
/**
* @ORM\Column(type="integer")
*/
protected $value;
/**
* @ORM\Column(type="datetime")
*/
protected $createdAt;
}
Пользователь голосует +1 за например за entry с id = 2. В таблице создается Vote c полями: кто голосовал (userId), за какую сущность (entity, entityId), как (value), ну и когда (createdAt).
Так как в проект это серверное API, мы используем сериализацию в json.
Не понятно, как настроить связи в doctrine, чтобы рейтинг сущности лежал внутри нее и при сериализации и выглядел бы примерно так:
{entry: {
id: 2,
rating: 1,
...
}}
РЕШЕНИЕ:
примерно такое
entity_subscriber:
class: Flavi\AppBundle\EventListener\EntitySubscriber
arguments:
- "@doctrine.orm.entity_manager"
tags:
- { name: jms_serializer.event_subscriber }
<?php
namespace Flavi\AppBundle\EventListener;
use Doctrine\ORM\EntityManager;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
class EntitySubscriber implements EventSubscriberInterface
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public static function getSubscribedEvents()
{
return array(
array('event' => Events::POST_SERIALIZE, 'method' => 'onPostSerialize'),
);
}
public function onPostSerialize(ObjectEvent $event)
{
//Добавляем рейтинг entity из таблицы votes
$id = $event->getObject()->getId();
$type = $event->getType()['name'];
$qb = $this->em->getRepository('FlaviAppBundle:Vote')->createQueryBuilder('v');
$qb->select('SUM(v.value) as rating');
$qb->where('v.entity = :entity AND v.entityId = :entity_id');
$qb->setParameter('entity', $type);
$qb->setParameter('entity_id', $id);
$result = $qb->getQuery()->getSingleScalarResult();
if ($result !== NULL) {
$event->getVisitor()->addData('rating', (integer) $result);
}
}
}