Answer the question
In order to leave comments, you need to log in
Overall ranking for different entity types in symfony 2?
Hello.
The project uses symfony 2, doctrine.
There is a task to make a common rating for different types of entity through one common entity vote.
Simplified we see it like this:
/**
* 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;
}
{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);
}
}
}
Answer the question
In order to leave comments, you need to log in
You will not be able to do this natively with the help of the doctrine in this case. Since you will not create connections between Vote and other entities!
I see this solution: since you are using JMSSerializerBundle to serialize entities, you can set up a subscriber that will check the type of the entity on pre_serialize, get a rating for it and add it to the serialization result.
You can read more about this here
I would make a VotableInterface with a setRating method and when saving the Vote, recalculate the rating for the entity that was voted for
interface VotableInterface
{
public function setRating($rating);
}
class Object implements VotableInterface
{
/**
* @ORM\Column(type="integer")
*/
private $rating;
public function setRating($rating)
{
$this->rating = $rating;
}
public function getRating()
{
return $this->rating;
}
}
class VoteListener
{
public function postPersist(LifecycleEventArgs $event)
{
$vote = $event->getEntity();
if (!$vote instanceof Vote) {
return;
}
/**
* @var Object $entity
*/
$entity = $vote->getEntityObject();
if (!$entity instanceof VotableInterface) {
// Exception
}
$entity->setRating($entity->getRating() + $vote->getValue());
// Update $entity
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question