Доктрина 2.0 / Один-ко-многим: много-к-одному

Я пытаюсь настроить ассоциацию сущностей «один-на-один-много-один-один» в Doctrine 2.0. Поскольку мне нужно поле «читать» в таблице ассоциации user_message, у меня есть 3 объекта.

User.php

namespace Console\Entity; use Doctrine\Common\Collections\ArrayCollection; /** * @Entity(repositoryClass="Console\Repository\User") * @Table(name="user") */ class User { /** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /** * @OneToMany(targetEntity="Message", mappedBy="users", cascade={"all"}, orphanRemoval=true) * @JoinTable(name="user_message", * joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="message_id", referencedColumnName="id", unique=true)} * ) */ protected $messages; public function __construct(){ $this->messages = new ArrayCollection(); } public function addMessage(Message $message){ $message->addUser($this); $this->messages[] = $message; } } 

message.php

 namespace Console\Entity; use Doctrine\Common\Collections\ArrayCollection; /** * @Entity(repositoryClass="Console\Repository\Message") * @Table(name="message") */ class Message { /** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /** * @Column(type="text") */ protected $value; /** * @OneToMany(targetEntity="User", mappedBy="messages", cascade={"all"}, orphanRemoval=true) * @JoinTable(name="user_message", * joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="message_id", referencedColumnName="id", unique=true)} * ) */ protected $users; public function __construct(){ $this->users = new ArrayCollection(); } /** * @param Console\Entity\User $user */ public function addUser(User $user){ $this->users[] = $user; } } 

UserMessage.php

 namespace Console\Entity; /** * @Entity * @Table(name="user_message") */ class UserMessage { /** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /** * @Column(name="user_id", type="integer") */ protected $userId; /** * @Column(name="message_id", type="integer") */ protected $messageId; /** * @Column(name="is_read", type="boolean") */ protected $isRead; public function isRead(){ return $this->isRead; } public function setIsRead($flag = true){ $this->isRead = (bool)$flag; } } 

dump.sql (генерируется из доктрины)

 CREATE TABLE IF NOT EXISTS `message` ( `id` int(11) NOT NULL AUTO_INCREMENT, `type_id` int(11) DEFAULT NULL, `value` longtext NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), KEY `IDX_B6BD307FC54C8C93` (`type_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; CREATE TABLE IF NOT EXISTS `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ip_id` int(11) DEFAULT NULL, `username` varchar(50) NOT NULL, `password` varchar(64) NOT NULL, `created` datetime NOT NULL, `last_action` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `UNIQ_8D93D649F85E0677` (`username`), UNIQUE KEY `UNIQ_8D93D649A03F5E9F` (`ip_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; CREATE TABLE IF NOT EXISTS `user_message` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `message_id` int(11) NOT NULL, `is_read` tinyint(1) NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; ALTER TABLE `message` ADD CONSTRAINT `message_ibfk_1` FOREIGN KEY (`type_id`) REFERENCES `message_type` (`id`); ALTER TABLE `user` ADD CONSTRAINT `user_ibfk_1` FOREIGN KEY (`ip_id`) REFERENCES `ip` (`id`); 

И теперь мой тест:

 $user = $em->find('Console\Entity\User', 1); $message = new Console\Entity\Message(); $message->setValue('TestNachricht'); $user->addMessage($message); $em->persist($user); $em->flush(); 

Что происходит: таблица сообщений заполнена, user_message пуст. Что я могу сделать, чтобы использовать таблицу user_message и что мне нужно сделать, чтобы установить сообщение «как»?

Спасибо за помощь

Я понял:

message.php

 namespace Console\Entity; use Doctrine\Common\Collections\ArrayCollection; /** * @Entity(repositoryClass="Console\Repository\Message") * @Table(name="message") * @HasLifecycleCallbacks */ class Message { /** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /** * @Column(type="text") */ protected $value; /** * @ManyToOne(targetEntity="Console\Entity\MessageType", cascade={"persist"}) */ protected $type; /** * @OneToMany(targetEntity="Console\Entity\UserMessage", mappedBy="message", cascade={"all"}, orphanRemoval=true) */ protected $userMessages; /** * @Column(type="datetime") */ protected $created; /** * @param Console\Entity\MessageType $type * @param string $value */ public function __construct(MessageType $type, $value){ $this->type = $type; $this->value = $value; $this->userMessages = new ArrayCollection(); } /** @PrePersist */ public function prePersist(){ $this->created = new \DateTime("now"); } /** * @return int */ public function getId(){ return $this->id; } /** * @return string */ public function getValue(){ return $this->value; } /** * @return Console\Entity\MessageType */ public function getType(){ return $this->type; } } 

User.php

 namespace Console\Entity; use Doctrine\Common\Collections\ArrayCollection; use Console\Resource\Resource; /** * @Entity(repositoryClass="Console\Repository\User") * @Table(name="user") * @HasLifecycleCallbacks */ class User implements Resource { /** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /** * @Column(type="string", length=50, unique=true) */ protected $username; /** * @Column(type="string", length=64) */ protected $password; /** * @OneToOne(targetEntity="Console\Entity\Ip", cascade={"all"}, orphanRemoval=true) */ protected $ip = null; /** * @OneToMany(targetEntity="Console\Entity\UserMessage", mappedBy="sender", cascade={"all"}, orphanRemoval=true) */ protected $sentMessages; /** * @OneToMany(targetEntity="Console\Entity\UserMessage", mappedBy="receiver", cascade={"all"}, orphanRemoval=true) */ protected $receivedMessages; /** * @Column(type="datetime") */ protected $created; /** * @Column(type="datetime", name="last_action", nullable=true) */ protected $lastAction; public function __construct($username, $password){ $this->username = $username; $this->password = hash_hmac(self::PASSWORD_ALGO, $password, self::PASSWORD_SALT); $this->sentMessages = new ArrayCollection(); $this->receivedMessages = new ArrayCollection(); } /** @PreUpdate */ public function preUpdate(){ $this->lastAction = new \DateTime("now"); } /** @PrePersist */ public function prePersist(){ $this->created = new \DateTime("now"); } /** * @return int */ public function getId(){ return $this->id; } /** * @return string */ public function getUsername(){ return $this->username; } /** * @return string */ public function getPassword(){ return $this->password; } /** * @return Console\Entity\Ip */ public function getIp(){ return $this->ip; } /** * @return Doctrine\Common\Collections\ArrayCollection */ public function getReceivedMessages(){ return $this->receivedMessages; } /** * @return \DateTime */ public function getCreated(){ return $this->created; } /** * @return \DateTime */ public function getLastAction(){ return $this->lastAction; } /** * @param Console\Entity\User $receiver * @param Message $message * @param type $isRead */ public function sendMessage(User $receiver, Message $message, $isRead = false){ $this->sentMessages[] = new UserMessage($this, $receiver, $message, $isRead); } /** * @param \DateTime $dateTime */ public function setLastAction(\DateTime $dateTime = null){ $this->lastAction = ($dateTime) ? $dateTime : new \DateTime("now"); } public function setIp(Ip $ip){ $this->ip = $ip; } public function removeIp(){ $this->ip = null; } public function getName(){ return $this->getUsername(); } } 

MessageUser.php

 namespace Console\Entity; /** * @Entity(repositoryClass="Console\Repository\UserMessage") * @Table(name="user_message") * @HasLifecycleCallbacks */ class UserMessage { /** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /** * @ManyToOne(targetEntity="Console\Entity\User", cascade={"all"}) */ protected $sender; /** * @ManyToOne(targetEntity="Console\Entity\User", cascade={"all"}) */ protected $receiver; /** * @ManyToOne(targetEntity="Console\Entity\Message", cascade={"all"}) */ protected $message; /** * @Column(name="is_read", type="boolean") */ protected $isRead = false; /** * @Column(name="read_at", type="datetime", nullable=true) */ protected $readAt = null; /** * @Column(type="datetime") */ protected $created; public function __construct(User $sender, User $receiver, Message $message, $isRead = false){ $this->sender = $sender; $this->receiver = $receiver; $this->message = $message; if($isRead) $this->setIsRead(); } /** @PrePersist */ public function prePersist(){ $this->created = new \DateTime("now"); } /** * @return int */ public function getId(){ return $this->id; } /** * @return Console\Entity\User */ public function getSender(){ return $this->sender; } /** * @return Console\Entity\User */ public function getReceiver(){ return $this->receiver; } /** * @return Console\Entity\Message */ public function getMessage(){ return $this->message; } /** * @return boolean */ public function isRead(){ return $this->isRead; } /** * @return \DateTime */ public function readAt(){ return $this->readAt; } public function setIsRead(){ $this->isRead = true; $this->readAt = new \DateTime("now"); } public function setUnread(){ $this->isRead = false; $this->readAt = null; } }