Autor Zpráva
Jirin
Profil
Zdravím,
používám Doctrine a konkrétně EntityListener. Pokud to osekám tak mám entitu:

/**
 * @ORM\Entity
 * @ORM\EntityListeners({"DiscussionModule\Model\Entities\Listeners\DiscussionConversationListener"})
 */
class DiscussionConversation extends BaseEntity
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type = "integer")
     */
    protected $id;
    
    /**
     * @ORM\Column(type = "text")
     */
    protected $text;
    
    /**
     * @ORM\Column(type = "integer")
     */
    protected $answersCount;
    
    /**
     * @ORM\ManyToOne(targetEntity = "DiscussionModule\Model\Entities\DiscussionConversation")
     */
    protected $lastAnswer;
}

A EntityListener mi pak obstarává, že aktualizuje počet odpovědí a nastaví poslední reakci:
class DiscussionConversationListener
{
    
    /**
     * @ORM\PostPersist
     * @ORM\PostRemove
     */
    public function recountAnswersCount(DiscussionConversation $conversation, LifecycleEventArgs $event){
        $count = $event->getEntityManager()->createQuery('SELECT COUNT(c2.id) FROM ' . DiscussionConversation::getClassName() . ' c2 JOIN c2.user u '
                . 'WHERE u.hashRegistered IS NULL AND c2.topic = :topic AND c2.mainTopic = FALSE')
            ->setParameter('topic', $conversation->getTopic())
            ->getSingleScalarResult();
        
        $qb = $event->getEntityManager()->createQueryBuilder();
        $qb->update(DiscussionConversation::getClassName(), 'c')
            ->set('c.answersCount', $count)
            ->where('c.topic = :topic AND c.mainTopic = TRUE')
            ->setParameter('topic', $conversation->getTopic())
            ->getQuery()
            ->execute();
    }
        
    /**
     * @ORM\PostPersist
     * @ORM\PostRemove
     */
    public function lastConversationUpdate(DiscussionConversation $conversation, LifecycleEventArgs $event){        
        $last = $event->getEntityManager()->createQuery('SELECT c FROM ' . DiscussionConversation::getClassName() . ' c JOIN c.user u '
            . 'WHERE u.hashRegistered IS NULL AND c.topic = :topic  AND c.mainTopic = FALSE ORDER BY c.dateInserted DESC')
            ->setParameter('topic', $conversation->getTopic())
            ->setMaxResults(1)
            ->getOneOrNullResult();
        
        if($last === NULL){
            return;
        }
        
        $qb = $event->getEntityManager()->createQueryBuilder();
        $qb->update(DiscussionConversation::getClassName(), 's')
            ->set('s.lastConversation', $last->getId())
            ->where('s = :subject')
            ->setParameter('subject', $conversation->getTopic())
            ->getQuery()
            ->execute();
    }
}

No a pokud zavolám $em->flush()

tak se změny provedou všechny správně. Ale PostPersist/PostRemove prip. i PreRemove a PrePersist, se provedou izolovane od transakce. Je to pravděpodobně tím, že pokládám vlastně dtaz a volám přímo execute().

Ale nejde to vyřešit nějak chytře, protože je tohle přece blbost, když spadne spojení či něco, tka chci rollback přece. Teď to musím řešit tak, že to třeba ten $em->remove obalim do $em->transactional - pak se to provede v jedne transakci, ale je to takové nehezké dle mě, nejde to řešit nějak lépe?

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: