Я искал подробный ответ на этот вопрос, но не смог его решить. Недавно я работал с (и учился) CakePHP и сталкивался с препятствиями. Чтобы упростить мою базу данных, допустим, у нас просто две таблицы:
relationships
persons
(или persons_persons
)
У людей есть много-много отношений с самим собой – и действительно, у двух человек может быть более чем одна взаимосвязь между собой:
persons ------- *person_id* name relationships ------------- *relationship_id* person_1_id person_2_id start_date end_date
Теперь, если я хочу сказать, что Person1 (id = 1) женат на Person2, у меня будет одна запись в таблице relationships
. person_1_id
– 1
, а person_2_id
– два.
Я могу создать эти отношения в CakePHP и показать списки отношений (и лиц) на запись Person. Однако это однонаправленное отношение: для Лица 1 запрос будет только тянуть объекты Relationship
где соответствует person_1_id
. Если я хочу запросить отношения для Person 2, мне придется иметь вторую идентичную строку с person_1_id
и person_2_id
.
Вот модели:
class Member extends AppModel { public $hasMany = array( 'Relationships' => array( 'className' => 'Relationship', 'foreignKey' => 'person_1_id' ) ); } class Relationship extends AppModel { public $belongsTo = array( 'Person1' => array( 'className' => 'Person', 'foreignKey' => 'person_1_id' ), 'Person2' => array( 'className' => 'Person', 'foreignKey' => 'person_2_id' ) ); }
Какие-либо предложения? Логически не логично дублировать объекты связи, когда person_1_id на самом деле не является отдельным, чем person_2_id.
Я думаю, у вас есть два варианта:
Посмотрите на это с другой точки зрения; Рассмотрим понятие направленного против неориентированного графа. Ваша текущая схема поддерживает направленный край, оставляя один объект (Person) и прибывая на другой. Согласившись с точки зрения вашего приложения, человек не может иметь отношения с другим, не зная его.
Объем пространства в базе данных был бы незначительным, если бы вы решили пойти по этому маршруту и было бы менее сложно реализовать, чем вариант 2. Не стоит забывать, что вы должны принять меры для обеспечения того, чтобы отношения оставались симметричными в любое время.
Создайте еще одно соотношение, чтобы ваша модель выглядела следующим образом:
class Member extends AppModel { public $hasMany = array( 'RelationshipsA' => array( 'className' => 'Relationship', 'foreignKey' => 'person_1_id' ), 'RelationshipsB' => array( 'className' => 'Relationship', 'foreignKey' => 'person_2_id' ) ); }
Затем у вас есть отдельные бункеры для ваших отношений в зависимости от того, на какой стороне отношений ваш человек существует. Затем вам нужно добавить дополнительную логику везде, чтобы вы могли обрабатывать ячейки отношений как одну однородную коллекцию.
Мне жаль, что я не могу быть более полезным, но я не могу придумать голову, как реализовать неориентированный граф, не создавая его поверх направленного.
Чтобы суммировать поток комментариев, установка finderQuery
в ассоциации hasMany
может замаскировать необходимость дублирования поиска для связи с person_2_id
( Documentation ):
'Relationship' => array( 'finderQuery' => 'SELECT Relationship.* FROM relationships AS Relationship WHERE Relationship.person_2_id = {$__cakeID__$} OR Relationship.person_1_id = {$__cakeID__$};' )
Это скрывает сложный механизм поиска, но для хранения отношений может потребоваться дальнейшая мысль.