【发布时间】:2015-10-06 14:53:48
【问题描述】:
这个EntitiesTable 与它自己有一个belongsToMany 关联:
class EntitiesTable extends AppTable
{
public function initialize(array $config) {
parent::initialize($config);
$this->belongsTo('Users');
$this->hasMany('Information');
$this->belongsToMany('LinkedEntities', array(
'className' => 'Entities',
'through' => 'Links',
'foreignKey' => 'from_id',
'targetForeignKey' => 'to_id'
));
$this->belongsToMany('Tags');
}
}
但是,这种关联只在一个方向上起作用。当表links 只包含一个条目[from_id: 1, to_id: 2] 时,$this->Entities->findById(1)->contain('LinkedEntities') 正确获取链接实体,但$this->Entities->findById(2)->contain('LinkedEntities') 没有。
一种解决方案是复制表links 中的每个条目并交换from_id 和to_id,但这是不可取的。我更希望有一个 belongsToMany 关联,将from_id 视为foreignKey,将to_id 视为targetForeignKey,反之亦然。
如何实现双向的 belongsToMany 自关联?
一个例子
考虑以下类似图的网络:
每个点都有一个id,可能还有一些附加信息(如标题或坐标),并存储在entities 表中。
现在可以使用表格links来表示点之间的连接:
from_id to_id
1 2
1 4
1 6
2 3
3 5
3 7
4 5
4 6
5 7
请注意,每个连接只存在一次,1-2 可以与 2-1 一样存储,从到到的方向无关紧要。
现在,如果我想让所有节点都连接到节点 1,我可以使用以下查询:
SELECT * FROM entities WHERE id IN (
SELECT to_id FROM links WHERE from_id = 1
) OR id IN (
SELECT from_id FROM links WHERE to_id = 1
)
看看这有多容易?我只需要确保检查两个方向,因为连接是双向的。
我想在 CakePHP 中映射这个关联。我知道这很可能目前是不可能的,这就是我打开issue in the CakePHP github 的原因。
【问题讨论】:
-
相关问题:stackoverflow.com/q/20832098/2580794 该解决方案仅适用于旧版本的 CakePHP,因为选项
finderQuery已删除。 -
尝试通过 $id 查找 Entities,并将条件添加到可包含的 LinkedEntities WHERE is from_id = $id OR to_id = $id book.cakephp.org/3.0/en/orm/…
-
添加附加条件只会进一步限制链接的实体,因为结果查询仍然需要 to_id 为 $id。
-
我认为您需要创建两个关联:LinkedToEntities 和 LinkedFromEntities。
-
也许foreignKeys 的命名有点糟糕。实际上,关联中没有 from 和 to,from_id 和 to_id 是可以互换的。除了 CakePHP 似乎无法处理这种情况外,一些链接实体没有任何逻辑理由处于一个或另一个关联中。
标签: cakephp orm cakephp-3.0 has-and-belongs-to-many bidirectional-relation