CakePHP 1.3 – Неизвестная колонка в разделе where

Я работаю над уже существующим проектом cakephp 1.3, и мне нужно добавить новую таблицу в базу данных. У меня это в моем контроллере:

$conditions = array('ShootingPlacement.person_id' => $id, 'Email.person_id' => $id, 'Email.shooting_placement_id' => 'ShootingPlacement.id'); $shootingPlacements = $this->ShootingPlacement->find('all', compact('conditions')); 

И это дает мне эту ошибку:

  Warning (512): SQL Error: 1054: Unknown column 'Email.person_id' in 'where clause' [CORE/cake/libs/model/datasources/dbo_source.php, line 684] 

И ths – это запрос, который он пытается создать:

  SELECT `ShootingPlacement`.`id`, ... FROM `shooting_placements` AS `ShootingPlacement` LEFT JOIN `people` AS `Person` ON (`ShootingPlacement`.`person_id` = `Person`.`id`) LEFT JOIN `shootings` AS `Shooting` ON (`ShootingPlacement`.`shooting_id` = `Shooting`.`id`) WHERE `ShootingPlacement`.`person_id` = 123688 AND `Email`.`person_id` = 123688 AND `Email`.`shooting_placement_id` = 'ShootingPlacement.id' ORDER BY `lastname` ASC 

Очевидно, что мой код контроллера неправильный, но я не уверен, как связать таблицу электронной почты с объектом ShootingPlacement. Я думаю, что мои модели верны. Пока у меня есть это:

  $conditions = array('ShootingPlacement.person_id' => $id); $shootingPlacements = $this->ShootingPlacement->find('all', compact('conditions')); 

Он будет извлекать строки из «Съемки», «Съемка и личность», я хочу, чтобы электронная почта тоже была там. Электронная почта имеет 2 внешних ключа: один из ShootinPlacement и один из Person.

Это модели, единственная, которую я создал, – это электронная почта, а остальное – правильная работа.

 class Email extends AppModel { var $name = 'Email'; var $belongsTo = array ( 'Person' => array ( 'className' => 'Person', 'foreignKey' => 'person_id' ), 'ShootingPlacement' => array ( 'className' => 'ShootingPlacement', 'foreignKey' => 'shooting_placement_id' ) ); } class ShootingPlacement extends AppModel { var $name = 'ShootingPlacement'; var $belongsTo = array ( 'Person' => array ( 'className' => 'Person', 'foreignKey' => 'person_id', 'order' => 'lastname ASC' ), 'Shooting' => array ( 'className' => 'Shooting', 'foreignKey' => 'shooting_id' ) ); } class Person extends AppModel { var $name = 'Person'; var $belongsTo = array ( 'PersonOrigin' => array ( 'className' => 'PersonOrigin', 'foreignKey' => 'person_origin_id' ) ); var $hasMany = array ( 'ShootingPlacement' => array ( 'className' => 'ShootingPlacement', 'foreignKey' => 'person_id', 'dependent' => false ) ); } class Shooting extends AppModel { var $name = 'Shooting'; var $belongsTo = array ( 'ShootingLocation' => array ( 'className' => 'ShootingLocation', 'foreignKey' => 'shooting_location_id' ), 'Emission' => array ( 'className' => 'Emission', 'foreignKey' => 'emission_id' ) ); } 

То, что мне нужно в представлении, – это пропустить переменную ShootingPlacement, и мне нужно, чтобы она содержала данные таблицы электронной почты для этого конкретного идентификатора ShootingPlacement и Person (как вы видите в запросе, Person и ShootingPlacement уже находятся в отношениях, я только необходимо, чтобы там тоже была электронная почта)

Вы должны быть очень осторожны с вашими отношениями. С быстрым взглядом на некоторые из этих ответов они, похоже, предлагают вам просто добавить соединение к модели электронной почты в вашу модель Person и полагаться на условия вашей находки, чтобы гарантировать, что ваш запрос не будет перерывать память вашего сервера.

Я предполагаю, что в первую очередь вы хотите, чтобы это отношение электронной почты было неявным во всех ваших запросах на Person, иначе вы могли бы просто указать соединение для каждого запроса, для которого вы хотели этого. В этом случае вы определенно хотите связать его, используя отношения модели .

Ваш код показывает, что «Съемка и съемка» (предположим, что это модель для моделирования отношения отображения) относятся к двум моделям. Кстати, стрельба belongsTo Эмиссии, которую мы еще здесь не видели. Я предполагаю, что это не применимо к текущему сценарию.

Теперь давайте предположим, что из-за того, что в вашей таблице электронной почты есть внешние ключи , это будет отношение hasOne , а не hasMany – так вот что вам нужно связать. Я собираюсь связать его с моделью ShootingPlacement, потому что это модель, которую вы запрашиваете, поэтому она должна быть центральной точкой, в которой модели объединяются вокруг нее. Структура мудрая, потому что все, кажется, происходит от вашей модели Person, я должен был бы предложить вам запросить эту модель вместо этого. Но способ, которым он настроен до сих пор, позволит вам запрашивать почти из любого места и по-прежнему извлекать в основном одну и ту же панель результатов несколько имен моделей и псевдонимов таблиц.

Чисто, потому что ваш внешний ключ между Email и ShootingPlacement имеет другое имя, а CakePHP 1.3 не справляется с этим очень хорошо, я также предлагаю вам не использовать внешний ключ, вместо этого вставляя его в отношения как условия .

 class ShootingPlacement extends AppModel { var $name = 'ShootingPlacement'; var $actsAs = array('Containable'); var $hasOne = array( 'Email' => array( 'className' => 'Email', 'foreignKey' => false, 'conditions' => array( 'Email.shooting_placement_id = ShootingPlacement.id', 'Email.person_id = ShootingPlacement.person_id' ) ) ); var $belongsTo = array ( 'Person' => array ( 'className' => 'Person', 'foreignKey' => 'person_id', 'order' => 'lastname ASC' ), 'Shooting' => array ( 'className' => 'Shooting', 'foreignKey' => 'shooting_id' ) ); } 

Я также добавил туда сдерживаемое поведение. Это позволяет вам управлять каждым запросом, какие связанные модели вы хотите вернуть с результатами вашей первичной модели. Он по умолчанию будет использоваться для всех, но может быть удобен, когда вам нужно только что-то определенное и / или по соображениям памяти (эти запросы могут быстро уничтожить вашу память сервера, если вы не ограничиваете их или указываете только имена полей, которые вы хотите вернуть).

Теперь, когда вы создаете свою модель электронной почты, я бы не стал более затруднять этот беспорядок запутанных моделей, снова связав его с ShootingPlacement. Как вы уже сказали, он также имеет внешний ключ для модели Person. Таким образом, вы можете сделать то же самое, что и выше для вашей модели Person (изменяя условия, чтобы, конечно, отображать внешний ключ Person). Таким образом, ваша модель немного более гибкая; он по-прежнему будет присоединяться к ShootingPlacement и Person, а также позволит вам запрашивать его отдельно, если потребуется, без других связанных моделей.

Документация

  • CakePHP 1.3 Модельные ассоциации
  • CakePHP 1.3 Контейнерное поведение

Смотрите также

  • Эта статья о Stack

В вашей модели добавьте сдерживаемое поведение

 class Email extends AppModel { var $name = 'Email'; var $actsAs = array('Containable'); var $belongsTo = array ( 'Person' => array ( 'className' => 'Person', 'foreignKey' => 'person_id' ), 'ShootingPlacement' => array ( 'className' => 'ShootingPlacement', 'foreignKey' => 'shooting_placement_id' ) ); } 

Просто напишите приведенный ниже код в своем контроллере.

 $this->ShootingPlacement->recursive = 2; $this->ShootingPlacement->contain = array( 'Shooting', 'Person' => array( 'Email' ) ); $conditions = array( 'ShootingPlacement.person_id' => $id, 'Email.shooting_placement_id' => 'ShootingPlacement.id' ); $shootingPlacements = $this->ShootingPlacement->find('all', compact('conditions')); 

Надеюсь, это поможет вам.

Добавьте отношение $ hasOne к модели Person с помощью электронной почты, как показано ниже.

 var $hasOne = array( 'Email' => array( 'className' => 'Email', 'foreignKey' => 'person_id' // Column defined for person ids in Email table ) ); 

Затем добавьте

 $this->ShootingPlacement->recursive = 2; 

ИЛИ вы можете просто использовать соединения в cakephp для присоединения к модели электронной почты. Обратитесь к столам для склеивания

Вам нужно связать свою модель ShootingPlacement с «Email», с которой вы ее называете.

 class ShootingPlacement extends AppModel var $name = 'Shooting'; var $hasMany= array ( 'Email' => array ( 'className' => 'Email', 'foreignKey' => 'yourfk' ), ); } 

И использует его очень мощный ContainableBehavior!

Пример:

 $contain=array('Email'=>array('fields'=>array('id','...'))); $conditions=array('ShootingPlacement.id'=>$yourId); $this->ShootingPlacement->attachBehaviros('Containable'); $this->ShootingPlacement->find('all',$conditions);// your will retrieve yoru SHootingItem + Emails linked - $contain=array('Email'=>array('fields'=>array('id','...'))); $conditions=array('ShootingPlacement.id'=>$yourId); $this->ShootingPlacement->attachBehaviros('Containable'); $this->ShootingPlacement->find('all',$conditions);// your will retrieve yoru SHootingItem + Emails linked 

Это обеспечит необходимое соединение:

 $conditions = array('ShootingPlacement.person_id' => $id, 'Email.person_id' => $id, 'Email.shooting_placement_id' => 'ShootingPlacement.id'); $joins = array( array( 'table' => 'emails', 'alias' => 'Email', 'type' => 'LEFT', 'conditions' => array('Email.shooting_placement_id = ShootingPlacement.id') ) ); $shootingPlacements = $this->ShootingPlacement->find('all', array( 'conditions' => $conditions, 'joins' => $joins ) );