同一模型上的双向belongsToMany关联

时间:2015-10-06 14:53:49

标签: cakephp orm cakephp-3.0 has-and-belongs-to-many bidirectional-relation

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_idto_id,但这是不可取的。我更愿意将belongsToMany关联视为from_idforeignKeyto_idtargetForeignKey,反之亦然。

如何实施双向belongsToMany自我关联?

示例

考虑以下类似图形的网络:

graph

每个点都有一个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

1 个答案:

答案 0 :(得分:0)

这有帮助吗?

$this->belongsToMany('LinkedEntities', [
    'className' => 'Entities',
    'through' => 'links',
    'conditions' => [
         'OR' => [
                'AND' =>['Links.from_id = LinkedEntities.id', 'Links.to_id = Entities.id'],
                'AND' => ['Links.to_id = LinkedEntities.id', 'Links.from_id = Entities.id']
            ],
    ],
]);

将其放在EntitiesTable