【问题标题】:Doctrine ORM - entity implements interfaceDoctrine ORM - 实体实现接口
【发布时间】:2015-04-09 18:40:36
【问题描述】:

我有以下问题 - 在项目中,我有一个名为 TaggableInterface 的接口

interface TaggableInterface {
   public function addTag(TagInterface $tag);
   public function deleteTag(TagInterface $tag);
   public function getTags();
}

它是由一些实体类实现的。

Doctrine 中有什么好的方法可以在这些实体和标签之间建立关系吗?如果 Taggable 不是接口而是抽象类,我可以通过实体继承来解决它..

如果没有 Doctrine,我可能会使用 Party/Accountability 设计模式 (http://martinfowler.com/apsupp/accountability.pdf)。

【问题讨论】:

    标签: php doctrine-orm doctrine


    【解决方案1】:

    如果我理解正确:您想在不使用抽象类和重复代码的情况下为接口创建映射和实现。

    PHP 有特点。您可以使用接口的通用实现来创建特征。根据经验,我知道您还可以将学说注释映射到 trait,一切都会正常运行。

    创建 TaggableTrait。它的行为类似于类或接口。它位于命名空间中,如果您使用 use 添加它,它将由您的自动加载器加载。

    namespace My\Namespace;
    
    use Doctrine\ORM\Mapping as ORM;
    
    trait TaggableTrait 
    {
    
       /**
        * @ORM\ManyToMany(targetEntity="Some\Namespace\Entity\Tag")
        */
       protected $tags;
    
       public function addTag(TagInterface $tag)
       {
          $this->tags->add($tag);
       }
    
       public function removeTag(TagInterface $tag)
       {
          $this->tags->removeElement($tags);
       }
    
       public function deleteTag(TagInterface $tag)
       {
          $this->removeTag($tag);
       }
    
       public function getTags()
       {
          return $this->tags;
       }
    
    }
    

    在您的可标记实体中:

    namespace Some\Namespace\Entity;
    
    use Some\Namespace\TaggableInterface;
    use My\Namespace\TaggableTrait;
    use Doctrine\ORM\Mapping as ORM;
    //...
    
    /**
     * @ORM\Entity
     */
    class TaggableEntity implements TaggableInterface
    {
       use TaggableTrait;
    
       public function __construct()
       {
          $this->tags = new ArrayCollection();
       }
    
       // rest of class code
    }
    

    请注意,use 类内部有不同的含义。它添加了 trait,与命名空间导入无关。

    您必须始终在构造函数中初始化 $tags,trait 不能这样做。

    这样您只能创建单向关联。如果您想要更多自定义,请从 trait 中删除映射并将其添加到类中。

    【讨论】:

    • 感谢您的回复,使用特征的有趣想法 :) 您能否告诉我一些特征方法之一的基本实现,例如addTag(我确定如何创建关系)?谢谢
    • @Jadro007 我编辑了我的答案。我还添加了removeTag,因为removeXXX 是一个学说/symfony 约定。这将确保 symfony 在通过表单编辑标签等情况下不会感到困惑。
    • nice :) 我理解正确吗,该学说为每个使用 TaggableTrait 的实体生成 M:N 关系实体?
    • 关系不是实体,也不表示为对象。它是通过检查您的 $tag 集合的状态来管理的。实体不等于数据库表。有时数据库表没有实体,有时一个实体由多个表表示。
    • 是的,它是在您运行doctrine:schema:update 时创建的。来自导入特征代码的注释与来自类代码的注释同等对待。
    【解决方案2】:

    最后我决定使用需要更多代码编写的更复杂的解决方案:

    每个实现Taggable的实体,都与它的可标记实体是一对一的关系,也就是多对多地连接到TagEntity。

    类图:


    创建这个数据库:


    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-27
      • 2021-02-23
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多