Limit to how deep a Many-To-Many will go with CakePHP - cakephp

Is there a limit to how deep a select all will go for a many-to-may relationship? I have a design like this:
Table Survey has many Table Survey Sections. Table Survey Sections have many Questions. Table Questions have many Table Possible Responses.
If I do this for the Survey Table:
$this->loadModel('Survey');
$this->Survey->recursive = 2;
$getSurvey = $this->Survey->find('all');
It will only go as far as the Questions table but bring back the Possible Responses Table. But, if I query the Survey Sections table, it brings everything back. Is this an issue with my code or a limit to how deep a search will go?
Here is my Models:
<?php
App::uses('AppModel', 'Model');
class Survey extends AppModel {
public $validate = array(
);
public $belongsTo = array(
);
public $hasMany = array(
'surveySection' => array(
'className' => 'SurveySection',
'foreignKey' => 'surveys_id',
),
);
}
<?php
App::uses('AppModel', 'Model');
class SurveySection extends AppModel {
public $validate = array(
);
public $belongsTo = array(
);
public $hasMany = array(
'Question' => array(
'className' => 'Question',
'foreignKey' => 'survey_section_id',
),
);
}
<?php
App::uses('AppModel', 'Model');
class Question extends AppModel {
public $validate = array(
);
public $belongsTo = array(
);
public $hasMany = array(
'PossibleResponse' => array(
'className' => 'PossibleResponse',
'foreignKey' => 'questions_id',
),
);
}
<?php
App::uses('AppModel', 'Model');
class PossibleResponse extends AppModel {
public $validate = array(
);
public $belongsTo = array(
);
}

You should use $this->Survey->recursive = 3;.
As I said in the comment, the example at http://book.cakephp.org/2.0/en/models/model-attributes.html#recursive is a bit misleading because it only show an example for a specific case. In fact you can go as far as you want when fetching data.

Related

How can I do an arbitrary level of recursion in CakePHP

I have a blog post model:
App::uses('AppModel', 'Model');
class BlogPost extends AppModel {
public $primaryKey = "ID";
public $useDbConfig = 'dev_blog';
public $useTable = 'posts';
public $hasMany = array(
'BlogComment' => array(
'foreignKey' => 'comment_post_ID',
'className' => 'BlogComment',
'order' => 'BlogComment.comment_date DESC',
'conditions' => array(
'BlogComment.comment_approved' => '1',
'BlogComment.comment_parent' => 0
)
)
);
}
And a blog comment model:
App::uses('AppModel', 'Model');
class BlogComment extends AppModel {
public $primaryKey = "comment_ID";
public $useDbConfig = 'dev_blog';
public $useTable = 'comments';
public $hasMany = array(
'Children' => array(
'className' => 'BlogComment',
'foreignKey' => 'comment_parent',
'order' => 'Children.comment_date DESC',
'conditions' => array(
'Children.comment_approved' => 1
)
)
);
}
In the controller, I set recursion on BlogPost equal to 2 and did a find:
$options = array(
'conditions' => array(
'BlogPost.ID' => $postID,
'BlogPost.post_status' => 'publish'
),
);
$post = $this->BlogPost->find('first', $options);
What this does is get the content of a particular blog post, all root comments and one level of replies to the root comments. It doesn't get a reply to a reply, though. How can I retrieve an arbitrary depth of replies?
Just don't use recursive at all. Ever.
Set it to -1 in the AppModel:
public $recursive = -1;
Then forget you even heard of it, and use CakePHP's awesome Containable Behavior to get the data you need.
Note: See the MANY other answers related to using CakePHP's Containable.

find() method in CakePHP not working, tried searching around and not resolve.

I'm just learning cakePHP. I have a CATEGORIES table and a POSTS table. A post have one category. So there is a category_id foreign key in POSTS table.
In my Model, I have Category.php with this code.
<?php
App::uses('AppModel', 'Model');
class Category extends AppModel {
// A hasMany association will allow us to fetch a category’s posts when we fetch a Category record.
public $primaryKey = 'category_id';
public $hasOne = 'Post';
}
?>
In my Post.php I have something like this.
class Post extends AppModel {
public $hasMany = array('Photo');
public $primaryKey = 'post_id';
public $belongsTo = array('User'); // 'Category',
public $relatedImages;
public $belongsTo = 'Category';
Now in my PostController.php I have
$allCategories = $this->Category->find('list');
$this->set('allCategories', $allCategories);
The objective is to retrieve all the category from the categories table and show it in my form.
However I encountered the error of Call to a member function find() on a non-object
I'm not sure what is happening here. How can I retrieve this?
many thanks!
Use
$this->Post->Category->find('list');
As you have to goto Category table Thru posts as u r in posts controller Now currently.
In your post model try to declare the Category as below
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
'Category' => array(
'className' => 'Category',
'foreignKey' => 'category_id'
)
);

How to Inherit $belongsTo of AppModel in Extended Model in Cakephp

In Cakephp,
I have used belongsTo in AppModel
class AppModel extends Model {
public $actsAs = array('Containable');
public $belongsTo = array(
'ModifiedBy' => array(
'className' => 'User',
'foreignKey' => 'common_modified_by_user_id'
)
);
}
Now I also want to apply belongs to in UserModel
class User extends AppModel {
public $belongsTo = array(
'School' => array(
'className' => 'User',
'foreignKey' => 'school_id'
)
);
}
But when i do so...it over rides the belongsTo of App model and on School data comes in the fetched array....
Please Help...
No automatic merging of associations
Other than the $actsAs and $findMethods variables, association configurations are not being merged automatically, you'll have to do that on your own.
It should be rather simple to solve, using Object::_mergeVars() in your User models constructor should do the trick:
public function __construct($id = false, $table = null, $ds = null) {
$parent = get_parent_class($this);
$this->_mergeVars(array('belongsTo'), $parent);
parent::__construct($id, $table, $ds);
}
ps. you might want to have a look at behaviors, they might be the better option for your needs.

Cakephp HABTM: Model not accessible in controller

I am trying to work with HABTM association between Profiles and Qualifications tables.
Model: Profile.php
App::uses('AppModel', 'Model');
class Profile extends AppModel {
public $hasAndBelongsToMany = array(
'Qualifications' => array(
'className' => 'Qualification',
'joinTable' => 'profile_qualifications',
'foreignKey' => 'profile_id',
'associationForeignKey' => 'qualification_id',
'unique' => 'keepExisting'
)
);
}
Model: Qualification.php
App::uses('AppModel', 'Model');
class Qualification extends AppModel {
public $hasAndBelongsToMany = array(
'Profile' => array(
'className' => 'Profile',
'joinTable' => 'profile_qualifications',
'foreignKey' => 'qualification_id',
'associationForeignKey' => 'profile_id',
'unique' => 'keepExisting',
)
);
}
Controller: ProfilesController.php
App::uses('AppController', 'Controller');
class ProfilesController extends AppController {
public function add() {
$qualifications = $this->Qualification->find('list'); /* Attempt 1 */
$qualifications = $this->Profile->Qualification->find('list'); /* Attempt 2 */
$qualifications = $this->Profile->ProfileQualification->Qualification->find('list'); /* Attempt 3 */
}
}
All three attempts mentioned as comment have given me an error saying:
Error: Call to a member function find() on a non-object
File: ~/app/Controller/ProfilesController.php
Line: xxx
I want to know how can I generate a list of all entries in Qualifications table ?
Moreover, what is the mistake in my code right now ?
In your Profile Model, the alias of your HABTM relation with Qualification is "Qualifications", so inside the controller you have to use : $qualifications = $this->Profile->Qualifications->find('list'); or remove the plural from the model.
To prevent these kind of mistakes and save your time, it's really useful to use automatic code generation with the cake bake console or an online CakePHP baking tool.

Models with two hasOne relations to same table

I'm building an MMA (mixed martial arts) website with CakePHP. I've got a fights table in my database that has three columns at its simplest: id, fighter_a, and fighter_b.
I'm having trouble getting my head around what type of relation my Fight model would have with my Fighter module. Am I right in thinking fighter_a and fighter_b would be two hasOne relations?
I tried this with the following in my Fight model:
<?php
class Fight extends AppModel {
public $name = 'Fight';
public $hasOne = array(
'FighterA' => array(
'className' => 'Fighter',
'foreignKey' => 'fighter_a'
),
'FighterB' => array(
'className' => 'Fighter',
'foreignKey' => 'fighter_b'
)
);
}
And then this in my Fighter model:
<?php
class Fighter extends AppModel {
public $name = 'Fighter';
public $hasMany = array(
'Fight'
);
}
But this threw an error in my CakePHP application when calling $this->Fight->findById($id) (where $id was the ID of a fighter):
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Fight.fighter_id' in 'field list'
How can I link my models so that I can call all fights a fighter has been in?
Distilled from conversation under the question, the solution would be this:
Rewrite the $hasMany in your FighterModel to look like:
public $hasMany = array(
'Fight' => array(
'className' => 'Fight',
'finderQuery' => 'SELECT * FROM fights AS Fight WHERE Fight.fighter_a_id = {$__cakeID__$} OR Fight.fighter_b_id = {$__cakeID__$};'
)
);

Resources