Laravel exclude voted posts - php

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();

Related

Laravel join table using eloquent

I'm trying to load last 5 comments with related posts selecting only id and title from post.
In first case I decided get all columns from posts:
Comment::with(['post'])->take(5)->orderBy('id', 'desc')->get();
And it's working fine.
But when I try get only two columns ("id, title") then nothing from posts is loaded.
Comment::with(['post:id,title'])->take($number)->orderBy('id', 'desc')->get();
I did a test and when I removed "orderBy('id', 'desc')" then was fine again.
Comment::with(['post:id,title'])->take($number)->get();
So must be some problem with "orderBy" option.
Is it any way to fix it? It's mean get only selected columns from "posts" table and order results from the last one?
Thank you.
As both your Comment and Post models contain id, Laravel doesn't know by which one do you want to sort. So, add a table name to your orderBy:
Comment::with(['post:id,title'])->take($number)->orderBy('comments.id', 'desc')->get();
Here comments is name of your table/entity, maybe it is comment.

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?

Mysql keep track of users views for each post in timelime

I have a screen that looks very much like facebook timeline
users can view posts of other users etc.
to get these posts i do something like
select user.id,user.name,posts.title,posts.body from posts left join users;
now data i need to collect is "Who saw this post" .
is there any elegant way to do it ?
right now all what i can think of is every time i fetch posts. i loop over them, then collect all ids of posts that the query returned and then push in another table
user_views [pk:user_id+postId]
userId,postId
1 , 1
Then when i'm fetching posts next time i can do count of user_views.
select *,count(user_views.id) from posts join user_views on post_id = post.id
but this sound like a lot of work for each VIEW, specially that most probably user will see a most multiple times,
is there any known patterns for such need ?
This is a design question and the answer really depends on your needs.
If you want to know exactly who viewed what post and how many times, then you need to collect the data on user - post level.
However, you may decide that you do not really care who viewed which post how many times, you just want to know how many times a post was viewed. In this case you may only have a table with post id and view count fields and you just increment the view count every time a post is being viewed.
Obviously, you can apply a mixed approach and have a detailed user - post table (perhaps even with timestamp) and have an aggregate table with post id and view count fields. The detailed table can be used to analyse your user's behaviour in a greater detail, or present them a track of their own activities, while your aggretage table can be used to quickly fetch overall view counts for a post. The aggregate table can be updated by a trigger.

Update parent model from child (belongsto) model

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.

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