How to change the sequence of "connections" in CakePHP?

I have a problem with the sequence of joins. A similar issue was in another issue Manipulating the JOINS order in CakePHP . The answer was to use Containable behavior. In my case, this is unacceptable because I have deeper associations and pent up generates too many requests. Containable does not create joins for three-level associations. It generates additional queries for each record from the second level table.

My request:

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

The problem is that cake generates several joins, but the join of the LevelThree table is performed before joining the LevelTwo tables and causes the SQL "LevelTwo.level_three_field_id" unknown column in the "on" section. If the LevelThree connection is at the end of the request after all LevelTwo connections are completed, everything will be fine.

So the question is how to change the sequence of joins?

+3
source share
5 answers

Finally, I figured out how to do this:

 $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' ) ) ) )); 
+5
source

Have you considered creating a HABTM model and adding your own "finderQuery" to override the model query? http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm

Sometimes with complex queries, it makes sense to create a custom query, so the cake should not deal with it. To do this, you can simply create a function in the model, and then call it just like any other request.

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

Then call it from the controller:

 $this->ModelName->customJoin(); 

I think that sometimes we rely too much on the automation that the infrastructure provides and forget that we control and can implement the code outside the kernel. I do this all the time. Hope this helps.

0
source

For those who have similar problems, but in the a-la $ relationship, Too owns, in order to have the correct order, you have to set it correctly.

For example, if you have a code like this:

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

But the result always results in which the vacancy is always connected last, you have to do simple things: add this model “Vacancy” not as an array value, but as a key => value, like others:

 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'), ), ); 

Now everything will be in order: Vacancy, Applicant, Recruiter and only then the Company.

0
source
 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); } 
0
source
 if (!in_array($join, $queryData['joins'])) { //$queryData['joins'][] = $join; array_unshift($queryData['joins'],$join); } 

Vous pouvez le fichier DboSource.php du coeur modifier (ligne 1510).

-1
source

All Articles