How do I get data from associated models in CakePHP? - cakephp

I create a simple blog with cakephp where i have some posts and some comments.
After i bake an application it create a comments folder with the index.ctp and a posts folder with the index.ctp
What i want to do is display them as fallow:
Post1
comment1
comment2
Post2
comment1
comment2
If i place the comments inside the posts/index.ctp i get an error telling me that the $comments is not defined.
How can i do this?
Thanks
edit:
alright, im sorry for the comeback, but it's still a bit unclear. I do have the $hasMany relationship setup, in fact on the page that displays the posts i have a link that points me to the comments. The only thing that i want them to be displayed in the same page as the posts.
i should be able to say <?php echo $comment['Comment']['content']; ?>

Check your controllers.
If you want to display Comment information in a Posts view, you need to be sure that the Posts controller can load the data.
The "CakePHP" way is to define relationships between models. Check your baked models and see if there is something like this:
class Post extends AppModel{
var $hasMany = array( 'Comment' );
}
When the models are associated with each other, your Posts controller will automatically find Post objects and their associated Comment objects.
For instance, this line:
$this->Post->findById( $id );
Will produce something like this:
Array
(
[Post] => Array
(
[id] => 42
[text] => Post1
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[post_id] => 42
[text] => Comment1
)
[1] => Array
(
[id] => 2
[post_id] => 42
[text] => Comment2
)
)
)
Good documentation at http://book.cakephp.org/
Model Associations
Retreiving Data
EDIT: Adding more info after your comment
As long as the models have the association, CakePHP will pull the data appropriately (unless you set Recursive => false or are using Containable which I assume you aren't).
Check your PostsController controller and see how it's loading the data. I'm guessing it is doing something like the following:
$post = $this->Post->findById( $id );
$this->set( compact( 'post' ) );
or
$this->data = $this->Post->findById( $id );
Check which way it is storing the retrieved data, and then access that variable from the view.
For example, if it is storing the data in a variable named "$post", you would put something like this in your view:
// output the 'text' field of the 'post' object
echo $post[ 'post' ][ 'text' ];
// loop through associated comments
foreach ( $post[ 'comment' ] as $comment ){
//output the 'text' field of a 'comment' object
echo $comment[ 'text' ];
}
By default CakePHP stashes tons of detail in arrays after retrieving data. The trick is to know the hierarchy of the data and fetch it from the array accordingly.

Related

Saving a model with no data in CakePHP (just create id in db)

My CakePHP Cart model/table has only one field: id.
It hasMany LineItems.
I am not having success saving the Cart model alone:
$this->Cart->create();
$this->Cart->save();
Or, by passing it a $data array structured as follows and using saveAssociated():
$data = array(
'Cart' => array(),
'LineItem' => array(
array(
'item_id' => $item_id,
'qty' => $qty,
'price_option_id' => $price_option_id
)
)
);
If I add a useless_field to the Cart table/model, and pass some data in it saves. So obviously the problem lies in my having a model with a table with just a single id field and not passing in any other data to save. It won't create what it must be assuming is an 'empty' record.
I have passed 'validate' => false into the saveAssociated call but it doesn't make a difference (and there are no validations for this model to ignore).
Is there a way to do this? Am I missing something? Please enlighten me!
CakePHP tables require created and modified fields, or for you to define your own fields (ie you can call them whatever you want but they do the same thing).
In this instance you would use
$this->Cart->set($data);
$this->Cart->saveAll();

CakePHP - Retrieving a list of options from another table, to use with form helper/ before Instering

Here is Yet another cakePHP question! I have table called blood_groups which has blood_group_id and group fields.. Then I have another table called donors, which has several fields such as name, surname etc. Another field included inside this table is the foreign key 'blood_group_id' which will need to map to the blood_group table on retrieval. in the donor registration view, i want to be able to retrieve the values from the blood_groups table, and display them using the formHelper (with their respective id's).
I have gone through CAKE doc, and I understand that I would need to create the association between my models, but I am struggling to figure this one out. Should I create $hasOne association inside the Donor Model (considering that the Donor table has the fk of the other table). And how would I go about retrieving the options of blood_groups from the blood_groups Model?
Should It work like this?(and are any other prerequisites involved?) :
In my DonorController -
$this->set('blood_groups', $this->Donor->Blood_Group->find('all'));
in Views/Donor/add.ctp
echo $this->Form->input('blood_group_id');
Accessing data through associations is fine. But for radios or checkboxes you want to do a find('list). Your model and variable name does not match the CakePHP convention, there should be no underscore.
Properly named this should be already enough to populate the input.
// controller
$this->set('bloodGroups', $this->Donor->BloodGroup->find('list'));
// view
echo $this->Form->input('blood_group_id');
If you don't follow the conventions for some reason:
echo $this->Form->input('blood_group_id', array(
'options' => $bloodGroups
));
See:
Linking Models Together
The Form Helper
Create one function in BloodGroup Model
function getDonors(){
$options = array(
// 'conditions' => array('Donor.blood_group_id'=>$id),
'joins' => array(
array(
'alias' => 'Donor',
'table' => 'donors',
'type' => 'LEFT',
'conditions' => array(
'Donor.blood_group_id = BloodGroup.blood_group_id',
),
)
),
'fields' => array('Donor.name','Donor.surname','Donor.blood_group_id',
'BloodGroup.blood_group_id')
);
$returnData = $this->find('all',$options);
return $returnData;
}
Now from controller call this function
App::import('model','BloodGroup');
$BloodGroup = new BloodGroup;
$donorList = $BloodGroup->getDonors();
$this->set('donorList',$donorList);
In view file you will get list of donors in $donorList.

cakephp saving data for a related model's related model (not typo)

I've run into a bit of a problem saving data in cake php.
here are the models/relationships.
District hasMany Departments
Department hasMany Groups
I am in a view for creating new district, in which I've allowed the user to create multiple new departments. while creating each department, the user may create multiple groups for that dept. Now the trouble is I'm unsure of how to save the group data.
for each department that is created on the fly, im using the multiple index method for the inputs (i.e. "Department.0.name", Department.0.type) so this will be a cinch to save using the saveAll method. However, for each group that is created, i will need a department_id, and since none of the District's departments have yet been saved, they don't have an id. how can i save this new district's data, saving the new departments, and their associated new created groups? is there a way that i can address the name attribute of the group inputs that will create the proper association, something like "Department.0.Group.0.name", for instance?
Thanks in advance!!! if anything is unclear, please don't hesitate to say so, I'll be glad to rephrase.
What does your POST data array look like?
<?php
debug($this->data);
?>
If it is not in the correct format, the associated models won't get saved.. Cake knows to grab the "lastInsertId()" of the models which haven't been saved yet, so you don't have to worry about those... What i'm not sure about, and the docs don't really go into, is how deep the save goes. The example provided is as follows:
$this->data =
Array
(
[Article] => Array
(
[title] => My first article
)
[Comment] => Array
(
[0] => Array
(
[comment] => Comment 1
[user_id] => 1
)
[1] => Array
(
[comment] => Comment 2
[user_id] => 2
)
)
)
$this->Article->saveAll($this->data);
This is the correct structure (cakephp 1.3) for saving associated models of a 'hasMany' relationship, but i'm not sure if it goes any deeper than one child.
One thing that comes to my mind is to build the array according to the format above, but leave the parent model out. Then manually save the parent model data, grab the ::getLastInsertId(); then do a saveAll on departments and groups.
[UPDATE]
I just tested your theory and it will work the way you intend.
<?php
echo $this->Form->input('Department.0.Group.0.name');
?>
Will produce:
<input name="data[Department][0][Group][0][name]" type="text" id="Department0Group0name">
[UPDATE 2]
I did some exploring in lib/Cake/Model/Model.php and found this:
<?php
...
public function saveAssociated($data = null, $options = array()) {
...
... // code omitted.
...
if ($options['deep']) { // This will recurse infinitely through all associations
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
}
...
...
... // code omitted.
...
?>

How to sort data of bind table in cakephp 2.0

I need the data from various table. I bind them by using cakephp's $hasMany variable. The data is fetched successfully. But I need to sort the result coming from $hasMany table.
for eg. I have two tables
Survey
Questions
Now Survey table contains the data related to Survey like title, id, purpose and Questions table contains question for related survey. I bind questions table with survey in survey model. Now I have a field in Questions table with name ordering. I need to fetch data in that order.
How can I fetch it in that way?
Please help me.
If you want to sort the data directly when it is fetched from db
You can define default order when adding relations between tables in your models. In your Survey model:
var $hasMany = array(
'Question' => array(
'order' => 'ordering DESC'
)
);
See http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany.
You can also define custom ordering when retrieving data from your controller in your conditional array, http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#find:
$conditions = array(
'order' => array('Question.ordering DESC')
);
If you are paginating your result with the paginator component, you can setup it like in following example book.cakephp.org/2.0/en/core-libraries/components/pagination.html#query-setup:
public $paginate = array(
'order' => array(
'Question.ordering' => 'desc'
)
);
If you want to sort the data presented in the view
Here you can use the pagination helper (together with the pagination component in the controller) as:
echo $this->Paginator->sort('Question.ordering');
see book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#creating-sort-links
Sorry for removing 'http://' on the two last links, but I am not allowed to post more than two links (<10 rep).
In CakePHP you can sort by associated tables. but you need to sort by column, you should use something like this in your view:
<?php echo $this->Paginator->sort('Question.ordering'); ?>

Containable behavior does not return from depth 3 - CakePHP

I use CakePHP 1.2.6 and have the following relations:
Showcase HABTM User belongsTo Galleryitem hasOne Image
I try to get all the data related to a Showcase, and therefor also all its users with their Galleryitem -> Image. I use the following query:
$showcase = $this->Showcase->find('first',
array('conditions'=>array('Showcase.id'=>$id),
'contain'=> array(
'User' => array(
'Galleryitem' => array(
'Image'
)
)
)
)
);
This does returns and empty array of Galleryitem and thus no Image records at all.
If I try the following:
$showcase = $this->Showcase->User->find('first',
array(
'contain'=> array(
'Galleryitem' => array(
'Image'
)
)
)
);
I do get some data here about Image. So it seems the depth plays a role here.
Other factors that came to mind were the belongsTo relation between User and Galleryitem.
What causes my query not to return data from a depth of 3?
Update
The set of Showcase relations is in my project much more branched than I explain above. All the other branches properply show up. So I guess it has to do with specific relations in this branch, the User belongsTo Galleryitem.
Strange still, because the other branches contain this very same set of Galleryitem hasOne Image relation.
I usually go for the dot syntax (which I can't see in the book):
$this->Showcase->contain('User','User.GalleryItem','User.GalleryItem.Image');
$showcase = $this->Showcase->User->find('first');
although I'm struggling to find a three-deep example in any of my code.

Resources