2009-09-17 5 views
2

Я работаю над приложением, разработанным с использованием Zend Framework. Я определил отношения в модели, и могут использовать их с удовольствием, например:Zend Framework отношения - определение имен столбцов в findManyToManyRowset()?

$rowset = $row->findManyToManyRowset('People', 'Jobs'); 

Однако, я ударил проблема, когда возвращается набор строк имеет имена столбцов, которые являются одинаковыми в «Люди» и «Работа» , и, следовательно, объединяет ключи массива, теряя некоторые данные из последнего набора строк.

Я понимаю, что я могу передать Zend_Db_Select объект findManyToManyRowset() в качестве одного из параметров, но не может найти какой-либо документации, объясняющие, как использовать его в этом случае, например:

$select = $this->select()->from(array(
            'p' => 'people', 
            'j' => 'jobs' 
            ), 
           array( 
            'person_id' => 'p.id', 
            'job_id' => 'j.id', 
            'person_code' => 'p.code', 
            'job_code' => 'j.code' 
            ) 
           ); 

Если я пытаюсь использовать приведенный выше код, я получаю сообщение, такое как:

Error: No reference rule "" from table People to table Jobs 

Может ли кто-нибудь просветить меня о том, как это должно быть сделано? Я знаю, что могу изменить имена столбцов в базе данных, но я предпочел бы изменение кода, а не перепроектировать мою структуру БД и обновить весь связанный код.

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

[_data:protected] => Array 
    (
     [id] => 1 
     [code] => SX342 
    ) 

Приветствия,
Matt

ответ

1

Моя первая рекомендация заключается в том, что вы не должны называть столбцы такими родовыми именами, как id и code. Эти имена бессмысленны, и, как вы обнаружили, они также приводят к столкновениям при получении результатов в ассоциативном массиве.

Вы также неправильно используете интерфейс выбора. Вы должны указать только одну таблицу на звонок from() или join().

Наконец, я никогда не пытаюсь выполнять сложные запросы через интерфейс отношений Zend_Db_Table. Он предназначен только для простых случаев. Если у вас более сложный запрос, просто напишите SQL-запрос явно.

Смотрите также How to do a joined query in the ZF tables interface?

+0

Спасибо за ответ Билл. У вас есть какие-либо рекомендации относительно того, как столбцы должны быть названы или в более широком масштабе, рекомендации для хороших руководств по наилучшим методам проектирования баз данных? – fistameeny

+0

Например, вы можете использовать «person_id» в обеих таблицах вместо «person_id» в одной таблице и «id» в другой таблице. По возможности сделать столбцы с одним и тем же содержимым одинаковыми именами в таблицах. Аналогично «person_code» вместо простого «кода». В основном, создавайте имена столбцов в разных таблицах, по крайней мере, когда они являются таблицами, которые могут быть объединены в запрос. –

+0

Прочитайте первую главу «Стиль программирования SQL для Joe Celko для Smarties». Google Books включает первую главу в онлайн-превью: http://books.google.com/books?id=a9jtyioHfp8C –

2

Я знаю, что ответ приходит немного поздно, но вот некоторые вещи, которые укажут.

1) findManyToManyRowset($matchTable, $intersectionTable, $callerRefRule, $matchRefRule, $select); - если вы проходите мимо Zend_Db_Table_Select, вы должны будете пройти null для ознакомления с правилами.

2) Zend_Db_Table_Select перешел в findManyToManyRowset() должен быть создан из $matchTable и можно с уверенностью предположить, что в пунктах где i является псевдонимом для таблицы пересечений и m это псевдоним для таблицы соответствия.

3) В случае столкновений m выиграет имя ключа в ассоциативном массиве, возвращенном в php.Запрос выполнен выглядит следующим образом:

SELECT 
    `i`.*, `m`.* 
    FROM 
    `interscetTable` AS `i` 
    INNER JOIN 
    `matchTable` AS `m` 
    ON 
    `i`.`fk_m` = `m`.`pk` WHERE (`i`.`fk_o` = ?) 

4) Независимо от того, возвращаемое значение findManyToManyRowset() будет Rowset создан из $matchTable так, если вам нужно, чтобы захватить любую информацию из пересекающейся таблицы, в то же время захвата данные для таблицы соответствия, вам, вероятно, придется иметь пользовательский номер Zend_Db_Select и избегать использования материалов Zend_Db_Table для сопоставления данных в любом случае.

Так что рабочий пример с использованием «Люди» в качестве таблицы соответствия «Рабочие» в качестве таблицы пересечений и позволяет сказать «Клиенты» в качестве исходной таблицы. Предполагая в этом примере, что таблицы связывают между собой что-то вроде: Люди. id:... -> рабочие. person_id:client_id:job_id -> клиентов: id:...

$client = $clientTable->fetchRow(); /// grab a random client 

// fetch all people that have worked for the client ordered by their last name. 
$client->findManyToManyRowset("People", "Workers", null, null, 
    $peopleTable->select()->order('m.lastname')); 

// fetch all people that have worked for the client ordered by their hire date: 
// `workers`.`hiredate` 
$client->findManyToManyRowset("People", "Workers", null, null, 
    $peopleTable->select()->order('i.hiredate'));