我想创建具有分类词汇表的Tag实体类,将由多个实体使用。 是否有可能与三列建立多种关系? 我需要存储标签ID,实体ID和实体类名称。
所以我现在:
<?php
/**
* Taxonomy
*
* @ORM\Table(
* name="tag_taxonomy",
* indexes={
* @ORM\Index(name="tag_taxonomy_namex", columns={"name"})
* }
* )
* @ORM\HasLifecycleCallbacks
* @ORM\Entity
*/
class Taxonomy
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(name="name", type="string", length=50)
*/
protected $name;
/**
* @ORM\OneToMany(targetEntity="Tag", mappedBy="taxonomy", fetch="LAZY")
*/
protected $tags;
// .....
}
标签表:
<?php
/**
* Tag
*
* @ORM\Table(
* name="tag",
* indexes={
* @ORM\Index(name="namex", columns={"name"})
* }
* )
* @ORM\HasLifecycleCallbacks
* @ORM\Entity
*/
class Tag
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue
*/
protected $id;
/**
* @var string
* @ORM\Column(name="name", type="string", length=50)
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity="Taxonomy", inversedBy="tags", fetch="LAZY")
* @ORM\JoinColumn(name="taxonomy_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $taxonomy;
// ....
}
关系表:
<?php
/**
* @ORM\Table(
* name="tag_tagging",
* uniqueConstraints={
* @ORM\UniqueConstraint(name="tagging_idx", columns={"tag_id", "entity_name", "record_id"})
* },
* indexes={
* @ORM\Index(name="entity_name_idx", columns={"entity_name", "record_id"})
* }
* )
* @ORM\HasLifecycleCallbacks
* @ORM\Entity
*/
class Tagging
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Tag", inversedBy="tagging", cascade="ALL")
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id", onDelete="CASCADE")
**/
protected $tag;
/**
* @var string
* @ORM\Column(name="entity_name", type="string", length=100)
*/
protected $entityName;
/**
* @var int
* @ORM\Column(name="record_id", type="integer")
*/
protected $recordId;
// .....
}
所以我已经将关系表与3列作为关键: &#34; tag_id&#34;,&#34; entity_name&#34;,&#34; record_id&#34;。 现在任何想法如何创建与任何实体的关系,标记表? 可能根本不需要标记实体吗?
我想知道为任何实体类型创建Tag实体的最佳方法是什么。 所以我可以为用户,文章,任何东西使用标签。 当然可以有很多关系,它会为每个实体创建单独的关系表吗?但这是正确的方法吗?
答案 0 :(得分:4)
即使不允许在任何实体和Tagging
类之间创建真正的关联(使用底层外键),您的方法也可以。不过,这完全可以接受。您需要从中获得一种方法来定义将进入entityName
字段的内容,以便它可以有效地充当鉴别字段。
正如您所说,您还可以为每个可以标记的实体提供单独的连接表。这是我目前在我的一个项目中使用的解决方案,它也正常工作。最后,它取决于您希望能够轻松执行的操作。
Tagging
表/实体您选择的这种方法也是FPNTagBundle中展示的方法,它集成了自己的DoctrineExtensions-Taggable库。它依赖于Tagging
实体,该实体是与ManyToOne
表Tag
关联的拥有方,并且包含两个字段(resourceId
和resourceType
)请参阅标记实体。
如果您想沿着这条路走下去,我建议您查看FPNTagBundle的Taggable原则扩展实现。或者,您可以查看this other taggable extension。它非常相似,但它以不同的方式使用doctrine事件来处理保存/加载。
<强>优点:强>
Tag
可以与Tagging
<强>缺点:强>
Tag
或Tagging
Tagging
与您的实体之间的关系没有外键,因此您的应用程序必须处理删除孤立Tagging
条目(无法依赖ON DELETE CASCADE
)tags
字段时正确保管。ManyToMany
关联使用这种方法,您最终会为每个实体提供一个连接表,声明与ManyToMany
实体建立Tag
关联。要快速向实体添加标签,我个人使用TaggableTrait
这样的一个:
trait TaggableTrait
{
/** @ORM\ManyToMany(targetEntity="AppBundle\Entity\Tag\Tag") */
private $tags;
/* ... getter and add/remove methods ... */
}
这样,在我的实体中使用简单的use TaggableTrait
语句,我就可以启用标记。
<强>优点:强>
WITH
<强>缺点:强>
Tag
位于反面,则需要为每个Taggable实体添加ManyToMany
关联的反转无论如何,正如我在开始时所说的,这一切都取决于你想用标签执行什么样的操作。与resourceId
实体内的两个字段resourceType
和Tagging
建立通用关系可能会让您在应用程序中获得更多灵活性,但在使用时也会有点棘手它涉及到为某些事情与学说合作。