2011-01-05 5 views
0

Предположим (из-за отсутствия лучшего примера) У меня есть модель Person и другая модель Twin (что означает пару близнецов). Близнецы имеют два внешних ключа Person, скажем first_born_id и second_born_id, ссылающиеся на поля id двух разных людей (в Person). Как настроить отношения в торте?Множественные отношения в CakePHP

Я думаю, номер будет иметь что-то вроде:

$belongsTo = array('FirstBorn' => array('className' => 'Person', 
             'foreignKey' => 'firstborn_id'), 
        'SecondBorn' => array('className' => 'Person', 
             'foreignKey' => 'secondborn_id')); 

Но как я должен настроить Person? Я мог бы сделать это нравится:

$hasOne = array('TwinAsFirstborn' => array('className' => 'Twin', 
              'foreignKey' => 'firstborn_id'), 
       'TwinAsSecondborn' => array('className' => 'Twin', 
              'foreignKey' => 'secondborn_id')); 

Но тогда, когда у меня есть человек, и я хочу знать о его близнец я должен был бы проверить оба отношения. Наверное, я надеюсь, что есть способ получить отношения «Твин» в Личном, представляющем любой из двух способов, которыми Человек может находиться в двойных отношениях.

Или есть лучший способ установить это?

ответ

1

Я согласен с примером Twin, немного запутанным. Позвольте мне предположить, что у вас есть модель Product (Twin в вашем примере), и к ней прилагается 2 Component моделей.

components: id - name 
products: id - component1_id - component2_id 

Я бы настроить продукт следующим образом:

var $belongsTo = array(
    'Component1' => array(
     'className' => 'Component', 
     'foreignKey' => 'component1_id' 
    ), 
    'Component2' => array(
     'className' => 'Component', 
     'foreignKey' => 'component2_id' 
    ) 
); 

и компонентов, как:

var $hasMany = array(
    'ProductWithComponentAsComponent1' => array(
     'className' => 'Product', 
     'foreignKey' => 'component1_id' 
    ), 
    'ProductWithComponentAsComponent2' => array(
     'className' => 'Product', 
     'foreignKey' => 'component2_id' 
    ) 
); 

В принципе, вы должны заменить ваш hasOne с hasMany. Каждый компонент имеет множество продуктов, где он является первым компонентом. В то же время он имеет множество продуктов, где он является вторым компонентом. Надеюсь, что все ясно.

EDIT 1: (О, и «ProductWithComponentAsComponent #» только с целью объяснения Вы можете сохранить все, что короткий, сладкий псевдоним вы хотите в зависимости от ваших реальных моделей..)

EDIT 2: Простое правило для использования hasOne отношений - Используйте его только тогда, когда вы разделив одну таблицу на много (например, User/Profile)

EDIT 3: Если вы хотите все продукты для компонента, то вы можете сделать это двумя способами.

(A) Определите foreignKey как false в вашем hasMany отношение.

var $hasMany = array(
    'Product' => array(
     'className' => 'Product', 
     'foreignKey' => false, 
     'conditions' => array(
      'or' => array(
       "Product.component1_id = Component.id", 
       "Product.component2_id = Component.id" 
      ) 
     ) 
    ) 
); 

(B) Если вышеуказанный метод не работает (странно, то и торт действует), вы также можете использовать объединение, чтобы сделать его слушаться. Создайте функцию в модели Component следующим образом:

function fetchProducts($id) { 
    if (!$id) { 
     return null; 
    } 
    return $this->Product->find('all', array(
     'fields' => array('Product.*'), 
     'joins' => array(
      array(
       'table' => 'components', 
       'alias' => 'Component', 
       'foreignKey' => false, 
       'type' => 'inner', 
       'conditions' => array(
        'or' => array(
         "Product.component1_id = Component.id", 
         "Product.component2_id = Component.id" 
        ), 
        'Component.id' => $id 
       ) 
      ) 
     ) 
    )); 
} 
+0

Возможно, я неправильно понимаю вас, но модель Component представляет собой экземпляр компонента (а не тип компонентов), а компонент может быть частью только одного продукта (также экземпляра, а не класса) либо как компонент1, либо компонент2. Значит, отношения не должны быть? Кроме того, с вашей моделью Component (в основном такой же, как у меня в первом примере, кроме hasOne-> hasMany) проблема остается о том, как получить доступ к Продукту Компонента, не проверяя оба отношения (мне может быть все равно, Компонент является компонентом1 или компонентом2 Продукта). – zephyr

+0

Вы можете заменить Component на ComponentInstance, если хотите. Обратитесь к разделу «Редактирование 2» относительно hasOne: используйте его, прежде всего, при разбиении таблиц. Чтобы получить доступ ко всем Продуктам компонента, см. Редактирование 3. :) – RabidFire

+0

А. Я не знал, что вы можете установить foreignKey в false (это где-то где-то?). Однако, похоже, он рекурсивно нарушает. С рекурсивным значением 2 для компонента я получаю сообщение «Неизвестный столбец: Component.id в WHERE», поскольку компонент отсутствует в отдельных запросах (из рекурсивности) в Product. Для регулярных заявленных отношений foreignKey эти типы запросов получают идентификатор как константу (например, «(3)» вместо «Компонент». «Id»). Можно было сделать что-то вроде вашего метода B, но я надеялся, что есть способ, который лучше интегрируется с остальной частью системы CakePHP. – zephyr

0

Почему вы определяете близнеца, как это?

Близнец, первый или второй рожденный человек. То, что связывает их с родителем, это факт, что они «ребенок», а их «DOB» - то же самое.

Так вы бы не сделать что-то вроде:

Person -> ID, Имя, Возраст, DOB, PARENT_ID

PARENT_ID хранится в Чайлдс записи, и близнец определяется путем сравнения всех детей под родителем для DOB?

Разве это упрощает настройку ваших отношений cakePHP?

+0

А, я думаю, что мой пример был не слишком хорошо выбран. В реальном приложении Person является типом компонента, а Twin - это продукт, состоящий из двух из этих компонентов (или, возможно, только одного из них). Таким образом, у двух «человек» нет другой связи, кроме того, что они вместе составляют пару «близнецов». – zephyr

+0

Ahhh Я вижу - и этот «комплект» компонентов имеет только 2 записи? Можете ли вы опубликовать свою текущую структуру данных? – diagonalbatman

+0

Да, могут быть только два компонента (и они имеют разные роли в продукте, поэтому они различаются по своей роли, а значит, «первенец» и «второсортный» в примере). Я не могу опубликовать фактический код, но модели выглядят точно так же, как в примере (плюс некоторые несвязанные вещи). Таблица базы данных компонентов имеет поле «id», а таблица продуктов имеет два поля внешнего ключа («component_a_id» и «component_b_id»), ссылающиеся на поле «id» компонента. – zephyr

Смежные вопросы