草庐IT

php - Doctrine 2.0/一对多 : Many-To-One

coder 2024-01-03 原文

我尝试在 Doctrine 2.0 中设置一对多/多对一实体关联。 因为我需要关联表 user_message 中的一个字段“读取”,所以我有 3 个实体。

用户.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;
    }

}

消息.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;
    }

}

用户信息.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(由 Doctrine 生成)

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 表以及我必须做什么,将消息设置为“已读”?

感谢帮助

最佳答案

我明白了:

消息.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;
    }

}

用户.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;
    }

}

关于php - Doctrine 2.0/一对多 : Many-To-One,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6097107/

有关php - Doctrine 2.0/一对多 : Many-To-One的更多相关文章

  1. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  2. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  3. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  4. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  5. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

  6. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  7. ruby-on-rails - has_one :through work?如何 - 2

    我有三个模型:classReleaseItem:pack_release_itemsendclassPack:pack_release_itemsendclassPackReleaseItem问题是,在执行期间,如果我将一个包添加到release_item,它并不知道该包是一个包。例如:Loadingdevelopmentenvironment(Rails2.1.0)>>item=ReleaseItem.new(:filename=>'MAESTRO.TXT')=>#>>pack=Pack.new(:filename=>'legion01.zip',:year=>1998)=>#>>i

  8. ruby-on-rails - Prawn PDF : I need to generate nested tables - 2

    我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested

  9. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  10. ruby - 怎么来的(a_method || :other) returns :other only when assigning to a var called a_method? - 2

    给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R

随机推荐