I am working on building a json Rest api with CakePHP. It works great, except I can't seem to get the proper structure to the response.
I two tables: Users and Profiles. Users hasOne Profiles. Profiles has a foreign key.
Models: Users.php (with public $hasOne = 'Profile'), Profiles.php
Controller: UsersController.php
The response is:
[2] => Array
(
[User] => Array
(
[id] => 3
[firstname] => test
[lastname] =>
[email] =>
[password] =>
[created] => 2012-09-04 16:44:04
[modified] => 2012-09-04 16:44:04
)
[Profile] => Array
(
[id] =>
[skill] =>
[user_id] =>
)
)
I really want the response to be like this:
[2] => Array
(
[User] => Array
(
[id] => 3
[firstname] => test
[lastname] =>
[email] =>
[Profile] => Array
(
[id] =>
[skill] =>
[user_id] =>
)
)
)
I have looked in the join(), bind(), containable...I can't seem to find the solution for nested table. Any ides to get Profile to be nested within the Users?
Cakephp won't do it, since it isn't the structure it uses to manage data. You will have to do it manually. If you are working with a single result (as the given by find('first')) Try something like this (I haven't tested it):
$result = $this->User->find('first', array('conditions' => array('User.id' => 1)));
Set::insert($result, 'User.Profile', $result['Profile']);
uset($result['Profile']);
Related
Here is my code in which there is a key for user_id in the posts array but I want to show the username instead of it's id. Where can I write a function like findUserNameById($id) and call it in a view.
<table>
<tr><td>Sr. No.</td><td>User</td><td>Post</td></tr>
<?php
$counter = 1;
foreach($topic['Post'] as $post) {
echo "<tr><td>".$counter."</td><td>".$post['user_id']."</td><td>".$post['body']."</td></tr>";
$counter++;
}
?>
</table>
here's my array:
Array
(
[Topic] => Array
(
[id] => 1
[user_id] => 0
[title] => Some title
[visible] => 1
[created] => 2014-09-20 02:03:42
[modified] => 2014-09-20 22:30:45
)
[User] => Array
(
[id] =>
[username] =>
[password] =>
[full_name] =>
[role] =>
[created] =>
[modified] =>
)
[Post] => Array
(
[0] => Array
(
[id] => 1
[topic_id] => 1
[user_id] => 0
[body] => CakePHP 1
[created] => 2014-09-20 02:08:51
[modified] => 2014-09-20 02:08:51
)
[1] => Array
(
[id] => 2
[topic_id] => 1
[user_id] => 0
[body] => CakePHP 2
[created] => 2014-09-20 02:08:51
[modified] => 2014-09-20 02:08:51
)
)
)
There's key for the user for the topic but that is not available in case of posts but I have the id.
You write a function like that in the User model (i.e., following the fat model, skinny controller pattern).
However, that is overkill since there is already a field method which should meet your needs.
Then you call your method in the controller, and send the data to the view via set
In CakePHP if I run the following find command
$this->Instructor->find('all');
the following is returned:
Array
(
[0] => Array
(
[Instructor] => Array
(
[id] => 1
[user_id] => 3
[bio] => A billionaire playboy, industrialist and ingenious engineer, Tony Stark suffers a severe chest injury during a kidnapping in which his captors attempt to force him to build a weapon of mass destruction. He instead creates a powered suit of armor to save his life and escape captivity. He later uses the suit to protect the world as Iron Man.
)
[User] => Array
(
[id] => 3
[first_name] => Tony
[last_name] => Stark
[asurite_user] => tstark
[asurite_id] =>
[password] =>
[email] => tstark#example.com
[created] => 2012-10-30 09:57:36
[modified] => 2012-10-30 09:57:36
)
[Course] => Array
(
[0] => Array
(
[id] => 1
[slug] => beatles
[sln] => AAA001
[course_number] =>
[title] => The Beatles
[description] => This is a class about the Beatles. If this were a real description, more information would be listed here.
[state] =>
)
[1] => Array
(
[id] => 2
[slug] => elvis
[sln] => AAA002
[course_number] =>
[title] => Elvis: The King of Rock
[description] => All about the king of rock and roll, Elvis Presley.
[state] =>
)
)
)
[1] => Array
(
...
There is a many-to-many relationship between "Instructor" and "Course". How can I filter the results based on the "Course"s each "Instructor" belongs to? I tried the following without success:
$instructors = $this->Instructor->find('all', array(
'conditions' => array('Course.id' = 2)
));
If you're trying to restrict your parent item based on conditions against your child item, you can either do your main query through the child model instead of the main model, and contain() the rest, or use MySQL Joins - available in CakePHP via joins().
You need to (re)bind the associations for your Instructor model with hasOne and use these settings:
'CoursesInstructor' => array(
'className' => 'CoursesInstructor',
'foreignKey' => false,
'conditions' => 'Instructor.id = CoursesInstructor.id'),
'Course' => array(
'className' => 'Course',
'foreignKey' => false,
'conditions' => 'CoursesInstructor.course_id = Course.id');
This will generate the correct SQL with the required joins and your conditions will work.
When I try to create a new entry of Template with the $data array, the models of Template, Group and Product are saved correctly. But the nested Calcfield (which is a hasMany of Group) is not saved. :( Group and Product are hasMany of Template.
Is this possible at all?
$this->Template->create();
$this->Template->saveAll($data, array('validate' => false));
// $data looks like this:
Array
(
[Template] => Array
(
[title] =>
[shorttitle] => Wie auch immer
[place] => Hannover
[size] =>
)
[Group] => Array
(
[0] => Array
(
[title] => Hosting
[order] =>
[Calcfield] => Array
(
[0] => Array
(
[title] => Hosting
[value] => 0
[description] =>
)
[1] => Array
(
[title] => Strom
[value] => 0
[description] =>
)
)
)
)
[Product] => Array
(
[0] => Array
(
[share] => 10
[businessunit] => Marketing
)
[1] => Array
(
[share] => 30
[businessunit] => intl. CRM
)
)
)
No, recursive saves are not possible, as far as I know. You would need to stick those in a separate array and then save them after the initial save.
Since CakePHP 2.1 it's possible to save deeply-nested models using the deep parameter in saveAll (since CakePHP 2.1)
ref. http://book.cakephp.org/2.0/en/models/saving-your-data.html?highlight=saveall#model-saveassociated
I am learning cakephp and doing an example.I have many tables in my database such as User,Post,Comment,Friend,Photo and each table has a foreign key user_id.Now I want to display user's photo,his/her friend's posts, comments on those posts,user's friends etc like any social networking site after successfull login.can any one please suggest me how to do that.
Thanks in advance.
You want to use the Containable Behavior to pull back a nested object graph that will have all of those fields.
http://book.cakephp.org/view/1323/Containable
You'll get back results like this (...pulled from the cakephp book)
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[post_id] => 1
[author] => Daniel
[email] => dan#example.com
[website] => http://example.com
[comment] => First comment
[created] => 2008-05-18 00:00:00
)
[1] => Array
(
[id] => 2
[post_id] => 1
[author] => Sam
[email] => sam#example.net
[website] => http://example.net
[comment] => Second comment
[created] => 2008-05-18 00:00:00
)
)
[Tag] => Array
(
[0] => Array
(
[id] => 1
[name] => Awesome
)
[1] => Array
(
[id] => 2
[name] => Baking
)
)
)
I've been banging my head against the wall with a really annoying issue. I have two model classes:
class User extends AppModel {
var $name = 'User';
var $hasMany = array(
'Application' => array(
'className' => 'Application',
'foreignKey' => 'user_id',
'dependent' => false,
)
);
}
class Application extends AppModel {
var $name = 'Application';
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
)
);
}
I want to pull Applications and the fields of User associated with it.
$this->Applications->find();
No matter what I set $recursive to, it's still giving me only one output:
Array
(
[Applications] => Array
(
[id] => 1
[user_id] => 3
[datecreated] =>
[status] =>
[source] => 1
)
)
On the other hand, when I pull the data from Users table with recursive set to 2, I get all the users, with their applications, WITH the user data associated with the application WITH the applications associated with the user. To put it plain and simple, here's what I get:
Array
(
[0] => Array
(
[User] => Array
(
[id] => 3
[email] => email#email.email
[password] => hashstring
[socialsecurityno] => 21232134123
[role_id] => 3
[firstname] => Firstname
[lastname] => Lastname
[status] => 1
)
[Application] => Array
(
[0] => Array
(
[id] => 1
[user_id] => 3
[datecreated] =>
[status] =>
[source] => 1
[User] => Array
(
[id] => 3
[email] => email#email.email
[password] => hashstring
[socialsecurityno] => 21232134123
[role_id] => 3
[firstname] => Firstname
[lastname] => Lastname
[status] => 1
[Application] => Array
(
[0] => Array
(
[id] => 1
[user_id] => 3
[datecreated] =>
[status] =>
[source] => 1
)
)
)
)
)
)
)
What I want, is to get from the Applications, its associated user info, and that's it. I'm pretty much out of ideas short of creating a habtm relationship between applications and users, which would be technically incorrect, as one user can have many applications but one application only has one user.
Right now, Applications is connected with Users via user_id in Applications table, which... should be kind of obvious, but probably should be noted anyway.
Any kind of help with this could be appreciated, I'm literally out of ideas.
If Model::find is called with no parameters, Cake treats it as though you made this request:
Model::find('first',array('limit'=>1));
This explains why it's only retrieving the first Application. To retrieve all Applications, modify your call to:
$this->Application->find('all');
This doesn't explain why Model::find is ignoring the model's recursive setting, and, indeed, I can't find a way to reproduce that issue, unless it's something silly like you have typoed the model name when setting the recursion level (e.g. $this->Applications->recursive = 1;; note the pluralization of "Application").
Hope this helps.