Как изменить последовательность «соединений» в CakePHP?

У меня проблема с последовательностью объединений. Аналогичная проблема была в другом вопросе « Манипулирование порядком JOINS в CakePHP» . Ответ состоял в том, чтобы использовать Containable behavior. В моем случае это неприемлемо, потому что у меня более глубокие ассоциации и сдерживаемые генерирует слишком много запросов. Containable не создает объединения для трехуровневых ассоциаций. Он генерирует дополнительные запросы для каждой записи из таблицы второго уровня.

Мой запрос:

$this->LevelOne->find('all', array( 'joins' => array(array( 'table' => 'level_three', 'alias' => 'LevelThree', 'type' => 'LEFT', 'conditions' => array( 'LevelThree.id = LevelTwo.level_three_field_id' ) )) )); 

Проблема здесь в том, что торт генерирует несколько объединений, но соединение таблицы LevelThree выполняется до объединения таблиц LevelTwo и вызывает SQL-ошибку «Неизвестный столбец» LevelTwo.level_three_field_id в разделе «on». Если соединение LevelThree будет в конце запроса после того, как все соединения LevelTwo будут выполнены, все будет в порядке.

Итак, вопрос в том, как изменить последовательность объединений?

Solutions Collecting From Web of "Как изменить последовательность «соединений» в CakePHP?"

Наконец, я понял, как это сделать:

 $this->LevelOne->unbindModel(array('belongsTo' => array('LevelTwo'))); $this->LevelOne->find('all', array( 'joins' => array( array( 'table' => 'level_two', 'alias' => 'LevelTwo', 'type' => 'LEFT', 'conditions' => array( 'LevelTwo.id = LevelOne.level_two_field_id' ) ), array( 'table' => 'level_three', 'alias' => 'LevelThree', 'type' => 'LEFT', 'conditions' => array( 'LevelThree.id = LevelTwo.level_three_field_id' ) ) ) )); 

Тем, у кого есть подобные проблемы, но в отношениях a-la $ принадлежит Too, чтобы иметь правильный порядок, вы должны установить его правильно.

Например, если у вас есть такой код:

 var $belongsTo = array( 'Vacancy', 'Applicant' => array( 'className' => 'Person', ), 'Recruiter' => array( 'className' => 'Person', ), 'Company' => array( 'conditions' => array('Company.id = Vacancy.company_id'), ), ); 

Но в результате всегда получайте результаты, в которых Vacancy всегда присоединяется последним, вам следует делать простые вещи: добавьте эту модель «Вакансия» не как значение массива, а как значение key =>, как и другие:

 var $belongsTo = array( 'Vacancy' => array(), // Just add empty array here -- all magic is here :) 'Applicant' => array( 'className' => 'Person', ), 'Recruiter' => array( 'className' => 'Person', ), 'Company' => array( 'conditions' => array('Company.id = Vacancy.company_id'), ), ); 

Теперь все будет в порядке: Вакансия, Заявитель, Рекрутер и только тогда Компания.

Вы думали о создании модели HABTM и добавлении собственного «finderQuery» для переопределения запроса модели? http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm

Иногда со сложными запросами, имеет смысл создавать пользовательский запрос, поэтому торт не должен иметь с ним дело. Для этого вы можете просто создать функцию в модели, а затем вызвать ее так же, как и любой другой запрос.

 function customJoin(){ return $this->query('CUSTOM QUERY HERE'); } 

Затем вызовите его из контроллера:

 $this->ModelName->customJoin(); 

Я думаю, что иногда мы слишком сильно полагаемся на автоматизацию, которую предоставляет инфраструктура, и забываем, что WE управляет и может реализовать код вне ядра. Я делаю это все время. Надеюсь это поможет.

 public function selectdata(){ $option= $this->Group->find('all', array( 'joins' => array( array( 'table'=> 'user_groups', 'alias'=>'g', 'type'=> 'INNER', 'conditions'=> array('g.group_id =Group.id ') ), array( 'table'=> 'users', 'alias'=>'u', 'type'=> 'INNER', 'conditions'=> array('u.id = g.user_id') ), ),'fields'=>array('Group.name,Group.created,Group.modified,Group.status,Group.created_by,u.first_name,u.last_name'), 'conditions'=>array('g.group_id=Group.created_by or g.user_id=u.id') // ."'".$created_by."'" ) ); var_dump($option);//die(); if(isset($this->params['requested'])) { return $option; } $this->set('groups', $option); } 
 if (!in_array($join, $queryData['joins'])) { //$queryData['joins'][] = $join; array_unshift($queryData['joins'],$join); } 

Модификатор Vous pouvez le fichier DboSource.php du coeur (ligne 1510).