该声明
我正在尝试重现用于处理多对多双向关系的自动 Doctrine 机制,但引入了自定义连接表。
我已经深入研究过类似的问题:
- 使用元数据连接表会损害 Getters/Setters - Doctrine 2 但它并没有真正帮助我,因为它绝对是单向的
- 学说2多对多自我引用,中间细节 ,但这个甚至没有谈论管理关系
- Doctrine2:使用参考表中的额外列处理多对多的最佳方法 非常有趣。然而,尽管作者提到了它的双向需求,但他并没有涵盖这种情况。
我知道带有额外字段的连接表不再是关联,只是引用另外两个实体的第三个实体。从该声明中,很明显,人们不能期望它作为由 Doctrine 管理的隐式多对多关联开箱即用。
但我想让这三重奏作为一个简单、直接、双向的多对多关联工作,这意味着使用代理方法并依赖逻辑类。
编码
有一个 Category 实体和一个 Product 实体:
/**
* @ORM\Table(name="category")
* @ORM\Entity(repositoryClass="CategoryRepository")
*/
class Category
{
/**
...
*/
protected $id = null;
/**
* @ORM\OneToMany(targetEntity="CategoryProduct", mappedBy="category", fetch="LAZY", cascade={"persist"})
*/
protected $categoryProducts;
}
和
/**
* @ORM\Table(name="product")
* @ORM\Entity(repositoryClass="ProductRepository")
*/
class Product
{
/**
...
*/
protected $id = null;
/**
* @ORM\OneToMany(targetEntity="CategoryProduct", mappedBy="product", fetch="LAZY", cascade={"persist"})
*/
protected $categoryProducts;
}
当然还有一个连接实体:
/**
* @ORM\Table(name="category_product")
* @ORM\Entity(repositoryClass="CategoryProductRepository")
*/
class CategoryProduct
{
/**
...
*/
protected $id = null;
/**
* @ORM\ManyToOne(targetEntity="Category", fetch="EAGER", inversedBy="categoryProducts")
* @ORM\JoinColumn(onDelete="CASCADE")
*/
protected $category;
/**
* @ORM\ManyToOne(targetEntity="Product", fetch="EAGER", inversedBy="categoryProducts")
* @ORM\JoinColumn(onDelete="CASCADE")
*/
protected $product;
/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $starred = false;
}
问题
如何以纯 ORM 样式的方式保持对两个实体都可用的 CategoryProduct 实体的最新列表?在 ORM 中,一切都在对象层上进行管理。仅根据用户的请求对 DB 进行更改,但只要仅从 ORM 的角度工作,就不是强制性的。换句话说:
$category->addProduct($product);
不会向数据库写入任何内容,甚至不会将任何对象持久化到实体管理器,但只要脚本运行,仍然可以从列表中检索或删除该产品。
在自定义连接表的情况下,情况有所不同,因为当想要添加产品时,他必须创建并持久化 CategoryProduct 实体。那么如果我们需要从反面检索这个关联呢?. 这是一个演示我的问题的代码示例:
$product->addCategory($category);
$category->addProduct($product);
在这种双向关联中,$category::addProduct
函数如何知道由创建的 CategoryProduct 实体的实例$product::addcategory
?风险是为同一个关联创建两个相似的连接实体,我不知道如何避免它。