How to get models order by relation value null and not null - laravel

I am using laravel 5.2 I have a question. There is Post model and Comment model. I want to get all posts with comments, whether they have comments or not. And I want to order posts by their comments, such as posts have comments are front, posts don't have comments are behind. How do I finish this? Thanks.

You can use withCount and order them by comments count as:
$posts = Post::withCount('comments')
->orderBy('comments_count', 'desc')
->get();
This will order the posts which have comments at first place and rest will follow it.
To count the number of results from a relationship without actually
loading them you may use the withCount method, which will place a
{relation}_count column on your resulting models.

Related

Laravel: Ordering posts by category in numerical order

In my application I want to order my posts by category in numerical order.
So I guess I need a mapping table like this:
category_id | post_id | sort_order
then setting up a kind of "Order model" with specific methods that handle it all and use this model as a relationship with the Post model.
But before I start on this project I'd like to know if there is not a Laravel package out there that does the job or another solution that I might have missed.
I'm not 100% sure, if I understand your need correctly, but I guess your posts are stored in a DB.
Then you can simply directly get the posts from DB ordered:
$posts = DB::table('posts')
->orderBy('category_id ', 'asc')
->orderBy('post_id', 'asc')
->get();
See the documentation:
https://laravel.com/docs/8.x/queries#ordering-grouping-limit-and-offset
I don't think, you need a Order model or something similar to realize this.

Laravel Eloquent: Order results by eaged loaded model.property, and paginate the result

Lets say I have three models: Post, Category and Tag.
The Post belongsTo Category and Category hasMany Post.
Theres manyToMany relation between Tag and Category.
I want to list my posts by Category name and paginate the results.
Post::with('category','category.tags')
->orderBy('category.name') //this is the bogus line
->paginate(10);
But this syntax doesn't work.
What I tried is this as:
Post::select('categories.*')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);
But then I lose the eager loaded data.
If I drop the select() clause then I get rubbish data as categories.id overwrites posts.id. See here.
Is there any elegant way to solve this issue? After spending hours on this I'm one step away from iterating through paginated posts and 'manually' loading the relations as:
foreach($posts as $post) {
$post->load('category','category.tags');
}
Not even sure if there's downside to this but it doesn't seem right. Please correct me if I'm wrong.
UPDATE on last step: Eager loading on paginated results won't work so if I go that road I'll need to implement even uglier fix.
You should be able to use both join and with.
Post::select('posts.*') // select the posts table fields here, not categories
->with('category','category.tags')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);
remember, the with clause does not alter your query. Only after the query is executed, it will collect the n+1 relations.
Your workaround indeed loses the eager loading benefits. But you can call load(..) on a collection/paginator (query result) as well, so calling ->paginate(10)->load('category','category.tags') is equivalent to the query above.

Laravel 5.2 eloquent model order by their relation model attribute

I have a question. I have an user model and a post model. A user can have many posts. Now I need to get posts with pagination. And I need to sort posts by their related user's id desc. Per page number is 10. I do not know how to write this code, someone can help me? Thanks.
Since Post belongs to User the posts table has user_id key. Use it:
Post::orderBy('user_id', 'desc')->paginate(10);

Translate query to Laravel Eloquent Model

How would I translate the following query into a format that Laravel can parse?
select posts.id,title from posts,albums where posts.id != albums.post_id
Now it has this ORM relations
a Post hasOne Album
an Album Belongs to a Post
So with this statement I want to know which Posts dont have Albums binded.
so far I have
Post::with('album')->select('id', 'title')->get();
I don't know how to declare the condition
Please do read docs again, I think you may look for polymorphic relationship or One to Many. If you use Eloquent ORM do use relationships its the biggest why "YES".
As for the query you can do http://laravel.com/docs/4.2/queries#raw-expressions
There is an example in a link just fill in your query and you are done.

laravel eloquent get related articles based on a tag

I'm a bit confused about how to do the following.
I have a table of articles and a table of tags with a many to many join and a pivot table between the two. I've got the relationships set up in the models
An articles can have more than one tag.
How can I easily(?) obtain a list of related articles for an article based on the tags attached to the current article.
I've tried querying from the tags side as follows:
foreach($article->tags()->get() as $tag) {
$relatedArticles .= Tag::with('articles')
->where('id','=', $tag->id)
->take(6)
->get();
}
This produces a nil response
I'm not sure about how to query from the articles to find articles with the tags dynamically.
So if an article has attached tag1 and tag2 I then want to retrieve all articles which have either tag1 or tag2 attached to them (ideally sorted on article date). The tags will be different for each article and may just be one or many.
Ideally i'd like to do this with an eloquent query but not essential - I'm not sure how to do in mysql either as a starting point.
Any help appreciated
Provided you are using Laravel 4.1, you can do something like this using the whereHas eloquent method:
$tag_ids = $article->tags()->lists('id');
$relatedArticles = Article::whereHas('tags', function($q) use ($tag_ids) {
$q->whereIn('id', $tag_ids);
})
->orderBy('created_at')
->take(6)
->get();
Breakdown
There's a few things going on here:
lists()
You can use the lists method on a select to get just a particular column, we're only concerned with the ID column in this case.
More info here: http://laravel.com/docs/queries#selects
whereHas()
We're using the new whereHas method which you can read.
More more about here: http://laravel.com/docs/eloquent#querying-relations
use()
Since the whereHas method accepts a closure (or 'anonymous function'), the function doesn't have any access to variables set externally, so we need to send them through to the function. We can do this with use.
More information here: http://www.php.net/manual/en/functions.anonymous.php

Resources