I want to display all comments along with all posts in a single page.For eg : I have 3 comments for POST A,2 comments for post B and so on.
It should look like this :
POST A - 3 Comments
POST B - 2 Comments and so on
So for this I have coded this :
$result = $this->Comment->find('all',array('fields'=>array('Comment.post_id','Comment.comments'),'group'=>'Comment.post_id'));
pr($a);exit;
$this->set('a',$a);
The array I got is this
Array
(
[0] => Array
(
[Comment] => Array
(
[post_id] => 1
[comments] => Nice Post...Nice Post...Nice Post...
)
)
[1] => Array
(
[Comment] => Array
(
[post_id] => 3
[comments] => wow..nice !!! Lorem Ipsum is simply dummy text of the printing and typesetting
)
)
)
I have total 3 comments for post_id = 1
I want all the three comments come together.
Remove ,'group'=>'Comment.post_id' from your find()
Depending on exactly what you mean, there are a number of ways to do that.
Find on Post
The question description is:
want to display all comments along with all posts
For that you'd only need to perform a find on Post, including Comment in the scope of the results. If your associations have been defined correctly that means:
$result = $Post->find('all', array(
'recursive' => 1
));
In this case, $result will be of the form:
[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
)
)
)
[1] => Array
(
[Post] => Array
(...
Instead of using recursive, you can use the containable behavior to fine-tune the amount of information returned.
Find on Post - counting comments
To get a list of posts and their comment counts - you need first to understand the sort of query required - e.g.:
SELECT
Post.id,
COUNT(Comment.id)
FROM
posts as Post
LEFT JOIN
comments as Comment ON (Post.id = Comment.post_id)
GROUP BY
Post.id
Without the join, any post with no comments will not be listed.
There are many ways to execute a query of that kind - here's one:
$result = $Post->find('all', array(
'fields' => array(
'Post.id',
'COUNT(Comment.id)'
),
'group' => array('Post.id'),
'joins' => array(
array(
'table' => 'comments',
'alias' => 'Comment',
'conditions' => array(
'Post.id = Comment.post_id'
)
)
)
));
Use find list
The group query in the question isn't the right structure unless there's an aggregate function used (count, sum, etc.). To get all comments grouped by post id - you can however use find list:
$result = $Comment->find('list', array(
'fields' => array(
'id',
'comments',
'post_id'
)
));
Used in this way the response format will be:
$result['post_id']['id']['comment']
i.e.:
array(
1 => array(
aa => 'Nice Post...Nice Post...Nice Post...',
bb => 'Another comment for post id 1'
),
3 => array(
cc => 'wow..nice !!! Lorem Ipsum is simply dummy text of the printing and typesetting ',
dd => 'Another comment for post id 3',
...
)
)
Related
I can't tell what I want but i can show:
This is my query:
select categories.name
, posts.url
, posts.name as postname
from categories
LEFT
JOIN posts
ON categories.id=post.category
where posts.home=1
and posts.view=1
order
by categories.position
, posts.position
It is coming like this:
[0] => Array
(
[name] => Cars
[url] => best-cars
[postname] => Top 10 Cars in 2018
)
[1] => Array
(
[name] => Cars
[url] => lorem-ipsum-dolor-1
[postname] => Lorem ipsum dolor 1
)
[2] => Array
(
[name] => Places
[url] => best-places-in-newyork
[postname] => Top 10 Places in New York
)
[3] => Array
(
[name] => Places
[url] => lorem-ipsum-dolor-2
[postname] => Lorem ipsum dolor 2
)
But I want it like this:
["Cars"] => Array
(
[url] => best-cars
[postname] => Top 10 Cars in 2018
)
["Places"] => Array
(
[url] => best-places-in-newyork
[postname] => Top 10 Places in New York
)
How can i do that? I want this because there is many posts in one category. I want list category name and all posts under this category. Thanks.
Use the name column as the array index in the result.
$result = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$result[$row['name']] = array('url' => $row['url'], 'postname' => $row['postname']);
}
Note that your desired result can only have one post for each category, even if there are multiple posts in the database, because array keys can't be repeated. You should consider making the value of each category an array of posts rather than just a single post. In the above code, the change would be:
$result[$row['name']][] = array('url' => $row['url'], 'postname' => $row['postname']);
Array
(
[Site] => Array
(
[id] => 1
[parent_id] => 0
[title] => test
[url] => http://www.test.com
[slug] => www_test_com
[keywords] => cpc,seo
[language_id] => 1
)
[SiteMeta] => Array
(
[0] => Array
(
[id] => 1
[site_id] => 1
[key] => pagerank
[value] => 5
[created] => 2010-08-03 00:00:00
)
)
)
By using cakephp, I debug my find('all') and returned me above array. I can sort Site field values by order value inside find function how I am able to order also with SiteMeta values
Any ideas?
Thanks
I'd do this in the Model as part of the association.
$hasMany = array('SiteMeta'=>array('order'=>array('SiteMeta.value'=>'asc')))
You won't have to repeat yourself anywhere then.
you can use a default query with a order condition like this:
$result = $this->Site->find('all', array(
'order'=>array('SiteMeta.value DESC' , 'Site.value DESC'),
'recursive'=>1));
Obviously you can put a condition inside the array to retrieve your right result
I would do it this way (as shown in the Docs)
$result = $this->Site
->find()
->contain([
'SiteMeta' => [
'sort' => ['SiteMeta.pagerank' => 'ASC']
]
]);
I have two tables in my database Members and Memberitems. I created two models for it. one is, Member and another is Memberitem
Member model has hasMany relation to Memberitem, and Memberitem model has belongsTo relations with my Member model.
Memberitem entries has specific categorization based on color, like, Red, Pink, Green, etc.
Now I want to select all the members who has atleast one Pink color memberitem using pagination.
Currently I am using:
$this->paginate = array(
'limit' => 5,
'contain' => array(
'Memberitem' => array(
'conditions' => array('Memberitem.color' => 'Pink')
)
)
);
But its showing all the Members.
output is this:
Array
(
[0] => Array
(
[Member] => Array
(
[id] => 1
[first_name] => fh
[last_name] => g
)
[Memberitem] => Array
(
[0] => Array
(
[id] => 1
[name] => item2
[color]=> Pink
)
)
)
[1] => Array
(
[Member] => Array
(
[id] => 2
[first_name] => ad
[last_name] => vd
)
[Memberitem] => Array
(
)
)
[2] => Array
(
[Member] => Array
(
[id] => 3
[first_name] => ae
[last_name] => sdi
)
[Memberitem] => Array
(
[0] => Array
(
[id] => 3
[name] => item1
[color]=> Pink
)
)
)
)
Its showing this result. Member of empty memberitem is still there. I want only 1st and 3 record in result.
This is a classic :-) It takes a while to get it though.
The Cake manual has an excellent peace on this. You should read: http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html#containing-deeper-associations
So if you want only Members with certain MemberItems, you should query on the MemberItems and contain the Member Model. You can actually do this from Member Model:
$this->Member->Memberitem->find('all', array(
'conditions' => 'Memberitem.color = "Pink"',
'contain' => 'Member',
));
or maybe a bit more catered to you app:
$this->paginate['Memberitem'] = array(
'contain' => array('Member'),
'conditions' => array(
'Memberitem.color' => 'Pink',
),
);
$items = $this->paginate('Memberitem');
Hope that helps!
I have the models User, Post, Comment and Tag.
User creates Post.
Posts can have multiple Comment and Tag.
Each model has it's own table, so there are tables 'posts', 'comments' and 'tags'. Comments have a foreign key called 'post_id', while Tags have a many_to_many relation table called 'post_tags', in which there are two fields: 'post_id' and 'tag_id'.
I want to get a nested array like below:
Which MySQL queries should I run?
I suppose I need to alter the result with PHP to get my nested array. How?
Thanks a lot for your help :-)
[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
)
)
)
[1] => Array
(
[Post] => Array
(...
You better of doing 3 queries.
first fetch post (, and left join the user if you need it), and store them like:
$list[$row['post_id']]['Post'] = $row;
then fetch all post-comments and store them as
$list[$row['post_id']]['Comment'][$row['comment_id']] = $row;
then fetch all post-tags
$list[$row['post_id']]['Tags'][$row['tag_id']] = $row;
that far more effective than trying to use a single query,
as a single query going to end up sending the same data multiple times
I have used join query which joins three tables employee, places and employee_places.The join query gives me all the results as I have used find('all').But in the view page I just want to show employee name from employee table - place name from place table in a dropdown.
e.g:- emp1-place1,emp2-place2 and so on. Where should I give the fields name in find.
Look at the following code :
$options['joins'] = array(
array('table' => 'employees',
'alias' => 'emp',
'type' => 'inner',
'conditions' => array(
'emp.id = EmployeePlace.employee_id '
)
),
array('table' => 'places',
'alias' => 'pl',
'type' => 'inner',
'conditions' => array(
'pl.id = EmployeePlace.place_id'
)
)
);
$empTables = $this->Bill->EmployeePlace->find('all', $options);
$this->set(compact('empTables'));
The above query results the following array:-
Array
(
[0] => Array
(
[EmployeePlace] => Array
(
[id] => 1
[employee_id] => 1
[place_id] => 1
[Date] => 2011-02-02
)
[Employee] => Array
(
[id] => 1
[image] =>
[firstName] => Andy
[lastName] => Murray
[date_of_joining] => 2010-09-02
[date_of_leaving] => 2011-02-02
[date_of_birth] => 1991-08-10
[gender] => Male
[supervisor] => 0
[designation] => Manager
[user_id] => 0
)
[Place] => Array
(
[id] => 1
[placeName] => table-1
[section_id] => 1
[position] => Left
[seating_capacity] => 4
)
)
)
I just want firstName from employee - placeName from place table in the dropdown. How do I do this using condition in find.
Use containable: http://book.cakephp.org/view/1323/Containable
You will then only be dealing with data that you require.
Loop over the results and build the strings you want. Add the strings to an array indexed against the value you want the selection to return. Pass the array out to the view.
How are you going to handle the values? What do you want to do when a user has made a selection?
OR:
You could create a db view, which is a table that combines data from other tables on the fly. CakePHP can access this as a normal table.