【问题标题】:Doctrine event sourcing - ManyToManyDoctrine 事件溯源 - 多对多
【发布时间】:2015-05-20 20:33:23
【问题描述】:

问题:¿如何获取具有给定状态的所有应用程序?

假设

  • 应用程序的状态是它的最后一个事件。
  • 事件具有递增的 ID。

活动:

<?php

namespace DnD\RaHApiBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints\DateTime;

/**
 * Event
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Event
{

  public function __construct($name = null, $type = null) {
    if (isset($name)) $this->name = $name;
    if (isset($type)) $this->type = $type;
    $this->eventDate = date_create(date("Y-m-d\TH:i:sO"));
  }

  /**
   * @var integer
   *
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @var string
   *
   * @ORM\Column(name="type", type="string", length=255, nullable=true)
   * @Groups({"application_info"})
   */
  private $type;

  /**
   * @var string
   *
   * @ORM\Column(name="name", type="string", length=255)
   * @Groups({"application_info"})
   */
  private $name;


  /**
   * @var date of event.
   *
   * @ORM\Column(name="event_date", type="datetime")
   * @Groups({"application_info"})
   */
  private $eventDate;

  ...
}

应用:

<?php

namespace DnD\RaHApiBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints\DateTime;

/**
 * Solicitud de registro.
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="DnD\RaHApiBundle\Repository\ApplicationRepository")
 */
class Application
{

  public function __construct()
  {
    $pending = new Event("PENDING", "APPLICATION");

    $this->status = new ArrayCollection($pending);
  }

  /**
   * @var integer
   *
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   * @Groups({"application_info"})
   */
  private $id;

  /**
   * @var string
   *
   * @ORM\Column(name="name", type="string", length=255)
   * @Groups({"application_info"})
   */
  private $name;

  /**
   * @var string
   *
   * @ORM\Column(name="dni", type="string", length=255)
   * @Groups({"application_info"})
   */
  private $dni;

  /**
   * @var string
   *
   * @ORM\Column(name="email", type="string", length=255)
   * @Groups({"application_info"})
   */
  private $email;

  /**
   * @var string
   *
   * @ORM\ManyToMany(targetEntity="DnD\RaHApiBundle\Entity\Event", cascade={"persist"})
   * @ORM\JoinTable(
   *      name="applications_events",
   *      joinColumns={@ORM\JoinColumn(name="application_id", referencedColumnName="id")},
   *      inverseJoinColumns={@ORM\JoinColumn(name="event_id", referencedColumnName="id", unique=true)}
   * )
   * @Groups({"application_info"})
   */
  private $status;
}

¿有没有办法获得具有给定“最后状态”的应用程序?

【问题讨论】:

    标签: database symfony doctrine-orm many-to-many event-sourcing


    【解决方案1】:

    您可以在 Application 存储库中进行自定义查询。

    使用doctrine 2 QueryBuilder,您的查询可能如下所示:

    public function getApplicationsByStatusId($id)
    {
        $applications = $this->createQueryBuilder('a')
            ->innerJoin('a.status', 's')
            ->where('s = :status_id')
            ->setParameter('status_id', $id)
            ->getQuery()
            ->getResult();
    
        return $applications;
    }
    

    由于它是ManyToMany 关联,因此您的结果可以是复数。

    【讨论】:

    • 这是在哪里寻找 LAST 状态?
    • @danielrvt 你说的是给定的最后状态,所以我假设你给了id。否则,您应该明确given last status 的含义。赋予什么属性?如果给出了其他一些状态属性,那么您只需将 where 子句更改为 -&gt;where('s.property = :value')
    【解决方案2】:

    对于事件溯源实现,您可以使用包rela589n/doctrine-event-sourcing

    
    class Message implements AggregateRoot
    {
        private Uuid $uuid;
    
        private MessageContent $content;
    
        private MessageStatus $status;
    
        private Carbon $createdAt;
    
        private Carbon $updatedAt;
    
        private User $user;
    
        private Chat $chat;
    
        /** @var Collection<MessageEvent> */
        private Collection $recordedEvents;
    
        /** @var MessageEvent[] */
        private array $newlyRecordedEvents = [];
    
        private function __construct(Uuid $uuid)
        {
            $this->uuid = $uuid;
            $this->status = MessageStatus::NEW();
            $this->recordedEvents = new ArrayCollection();
        }
    
        public static function write(Uuid $uuid, User $user, Chat $chat, MessageContent $content): self
        {
            $message = new self($uuid);
            $message->recordThat(
                MessageWritten::withData($message, $user, $chat, $content),
            );
    
            return $message;
        }
    
        public function edit(MessageContent $newContent): void
        {
            $this->recordThat(
                MessageWasEdited::with($this, $this->content, $newContent),
            );
        }
    
        private function recordThat(MessageEvent $event): void
        {
            switch (true) {
                case $event instanceof MessageWritten:
                    $this->createdAt = \Carbon\Carbon::instance($event->getTimestamp());
                    $this->user = $event->getUser();
                    $this->chat = $event->getChat();
                    $this->content = $event->getContent();
                    $this->chat->addMessage($this);
                    break;
                case $event instanceof MessageWasEdited:
                    $this->content = $event->getNewContent();
                    $this->status = $this->status->changingInto(MessageStatus::EDITED());
                    break;
                default:
                    throw new UnexpectedAggregateChangeEvent($event);
            }
    
            $this->updatedAt = \Carbon\Carbon::instance($event->getTimestamp());
            $this->newlyRecordedEvents[] = $event;
            $this->recordedEvents->add($event);
        }
    
        public function releaseEvents(): array
        {
            $events = $this->newlyRecordedEvents;
            $this->newlyRecordedEvents = [];
            return $events;
        }
    
        public function getPrimary(): Uuid
        {
            return $this->uuid;
        }
    
        public static function getPrimaryName(): string
        {
            return 'uuid';
        }
    }
    
    

    Message 是您的实体,MessageWrittenMessageWasEdited 是将保​​存在消息事件表中的事件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多