Update parent model from child (belongsto) model - php

I have Posts and Comments and users can "Like" either. I'm using cakePHP.
The Posts and Comments tables each have a 'likes' row on them because I don't want to re-count the likes each time the post / comments are loaded. I have a Likes table too, that contains the IDs (post id, user id) so that I know what users have already 'liked' something.
I was wondering how I would set up this relationship within the models in cakePHP and also how I would update Posts.likes field when at the same time adding a new like into the Likes table.
I've set up Likes to "belongTo" Posts and Comments in the Like Model and at the moment, my LikesController.php looks like this:
public function add(){
...
if ($this->Like->save($this->request->data)) {
//like is added to Likes table, now how to add to the "parent" Post or Comment??
}
...
}

Keep your tables as they are, but add a like_count field to your posts and comments tables.
Also add a comment_count to the posts table.
Then just use CakePHP's counterCache, and it will keep track of the # of likes and comments per post automatically.

Related

Laravel exclude voted posts

I have two tables: posts and votes, and I want to display only one post on home page, and then displaying them in random order. But I want to exclude posts that are already upvoted. So I want to loop only between not-voted posts. I am using Laravel 5.4
Structure for posts table:
id
user_id
...
Structure for votes table:
id
user_id
post_id
...
I just need a query for excluding posts, everything else I already have written.
Thanks
Assuming you have votes relationship in your Post model (I assume you use Eloquent) you can use:
$posts = Post::doesntHave('votes')->get();
to get posts that don't have any votes.
Obviously it might be not a good idea to run get() here as you will get all posts that don't have votes - and what in case there are 100 000 posts matching this criteria? You should probably only get some of them and then choose one random for example:
$posts = Post::doesntHave('votes')->latest()->take(100)->get();

CakePHP 3 - How to order find result by associated model

I am building a comment, with replies system using CakePHP and Backbone. But I am having some issues with my CakePHP query, that does not order in the way it needs to be.
So this is database system I have right now,
Posts
ID (Auto, PK)
MainPost (Long Text)
Timestamp
User_id
Comments
ID (Auto, PK)
SubComment (Long Text)
Timestamp
User_id
Post_id (FK, linking to the Posts table)
Now I think my model is ok (if needed I can post that code). I can save and update the posts and comments. But what I need to when a new comment is added to the system. That whole post is moved to the top.
This is the query I have done on my Posts Table,
$Table->find('all')
->contain(['Comments',
'Comments.Users',
])
// ->order(['Posts.Comments.timestamp' => 'DESC'])
// ->matching('Comments', function ($q) {
// return $q->where(['Comments.timestamp' => 'DESC']);
// })
->toArray();
So I want to do a sort, like my order looks above, I basically want to order my Posts Table based on the timestamp of my Comments Table.
When I run this query, with order enabled, it just says that "Unknown column" but I don't know why? I have a LeftJoin in my model linking the Comments to my Posts table.
I have tried doing sorts and orders within the contain call of the query, however these just sort/order the comments and not the posts!
So what am I doing wrong?

How can I look in different table to see if a page is active?

Some difficulties with "condition"
I have a table Tags with fields : id, name, count
I have table PagesTags with fields : id, page_id and tag_id
I have table Pages with several fields : id, name, shownmenu, onilne.
In my TagsController, I have a simple code to extract and display the Tags
function tagsList(){
//$this->loadModel('PageTag');
return $this->Tag->find('all',
array('order'=>'name ASC','conditions'=>array('Tag.count >= 0')));
}
The problem is, I do not want to display the tags associated to a page which is Offline.
Then in my aboce I should use somethink like $this->loadModel('PageTag'); to get the Id of the associated page and a second $this->loadModel('Page');
to get the page status 'online' (true/false)
Can we do it at once?
How can I do it simply?
How can I look in two table at one?
You need to use model relationships to link your models together. Read the manual about it or see my answer on this topic here:
CakePHP 1.3 - Unknown column in where clause
In your case, PagesTags hasOne Page and hasMany Tags. You will write these relationships into the model. Also you will write into Tags model that it hasOne PagesTags, which will in turn retrieve the associated Page.
After you have done all of that, you don't need to call loadModel, you just query Tag and it will implicitly join the associated PagesTags and Page records, so you can just put this into your conditions:
'Page.status !=' => 'Offline'
I think the relation of the table is HABTM so you have to look this component for searching http://bakery.cakephp.org/articles/Kumazatheef/2008/10/22/habtm-searching

Get the posts with more likes in the same lebel, in one table self referencing with doctrine and symfony2

I want to show all the replys to one post in symfony, but the replys need to be ordered by the amount of likes, that are saved in other table. The relation with the parent and the children are in the same table, and i don't know i are any form to get all the elements ordered in one query.

cakephp find all posts that have comments

I created a simple blog that has posts and comments. I want to find all the posts that have at least one comment and also find all the posts with no comments. Is there a cakephp way to do this? I.E. maybe something like
$this->Post->find('all', ???);
I ended up writing my own query, the example below finds all the posts with at least 1 comment
SELECT *
FROM (
select posts.*, count(comments.id) as comment_count
from posts left join comments on posts.id = comments.post_id
group by posts.id
) as T
WHERE comment_count != 0
but there seems like there would be a better way to do this.
Note: a Post hasMany Comment and Comment belongsTo Post
$grouped_comments = $this->Comment->find('all', array('group' => 'Comment.post_id'));
This will give you an array of all Comments grouped by post_id so you will have exactly one comment for each post, which is what you want. From there you can do whatever you want with that data.
Let's say you wanted to post a list of all post titles with comments.
echo "<H1>Posts with comments:</H1>";
foreach ($grouped_comments as $comment) {
echo $comment['Post']['Title'] . "<br>";
}
This of course only works if you have your model relationships set up in your comment.php model.
One solution would be:
$this->Post->find('all');
And your relationships are setup as you say above, the comments will already be returned with this information, you just need to run a count on them and handle the processing from there... something like:
$posts = $this->Post->find('all');
count($posts[0][Comment]);
There will likely be a more elegant way - as I'm new to CakePHP myself, but hopefully this has some value.
I'm still fairly new to CakePHP, but I think you could use counterCache to track the # of Comments per Post model record in a field in your Posts table, and then use some simple conditions in your Find to get what you are looking for. counterCache automatically updates the cache count field in the Parent model record field when children model records are added/deleted.
counterCache for CakePHP 1.2: http://book.cakephp.org/view/816/counterCache-Cache-your-count

Categories