1

Это EntitiesTable имеет ассоциацию belongsToMany с собой:Двунаправленного 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 и наоборот.

Как можно реализовать двунаправленную принадлежность?

Пример

Рассмотрим следующий график, как сеть:

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.

+0

: http://stackoverflow.com/q/20832098/2580794 Решение есть работает только для старых версий CakePHP, так как вариант 'finderQuery' был удален , –

+0

Попробуйте найти объекты по $ id и добавьте условия для сдерживаемых LinkedEntities. WHERE is from_id = $ id OR to_id = $ id http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets. html # pass-conditions-to-содержать – Salines

+0

Добавление дополнительных условий ограничивает связанные объекты далее, так как в результате запроса все равно требуется, чтобы to_id был $ id. –

ответ

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