This is my table.i need all post in descending order.I want advertised posts in top.
result example
Code
$data=Post::get();
Relationship in model
public function isAdvertised()
{
return $this->hasOne('App\models\PostAdvertise', 'post_id');
}
You can use leftJoin
$data = Post::leftJoin('post_advertise', 'post.id', '=', 'post_advertise.post_id')
->orderBy('post_advertise.created_at')
->select('post.id', 'post.title', 'post.description')
->get();
try
$posts = Post::with('isAdvertised')->all();
$sorted_posts = $posts->sortBy(function ($post, $key) {
return (is_null($post->isAdvertised) ? 1 : 0);
});
This will order the collection.
$posts = Post::orderBy('created_at','desc')->get();
You can then add this to your view:
#foreach($posts as $post)
$post->post_advertise->title
#endforeach
If it does not work I would advise you to post exactly what you did, like your migration, model(relationship) and controller.
Related
I have a many to many between Article and Category model and a pivot containing category_id and article_id records. At the click on the category link I would have a page that shows me all articles related to the category clicked but i can't create the right function in the controller.
public function showcategory($id){
$articles=Article::whereHas('categories',function($query){
$query->whereIn('category_id', $id);
})->get();
return view('categorydetail',compact('articles);
}
Your code seems not fine. Eloquent whereIn is expecting an array as second parameter. Use where instead.
$articles=Article::whereHas('categories',function($query){
$query->where('category_id', $id);
})->get();
Ideally, this is not the best practice. You'd better try the flow below:
//Category.php
public function articles() {
return $this->belongsTo(Article::class);
}
//Controller
$category = Category::with('articles')->find($id);
if (empty($category)) {
//show 404 error or redirection
}
$articles = $category->articles()->get();
Your code is correct, you just need to pass the id variable
The variable is passed using the code by adding the following code use($id)
You should use where instead of whereIn
public function showcategory($id){
$articles=Article::whereHas('categories',function($query) use($id){
$query->where('category_id', $id);
})->get();
return view('categorydetail',compact('articles));
}
There is also another way
public function showcategory($id){
$category= Category::find($id);
empty($category) ? abort(404) : '';
$articles = $category->articles()->paginate(10);
return view('categorydetail',compact('articles));
}
My query is:
$posts = Post::
whereIn('ID', (
NewsTag::
orderBy('post_date','desc')->with('publisher','newsTopics')
->paginate(12)->pluck('post_id')))
->get();
Newstag.php model is like this:
public function newsTopics() {
return $this->hasOne('App\Models\NewsTopics', 'post_id', 'post_id');
}
public function publisher() {
return $this->hasOne('App\Models\Publisher', 'id', 'publisher_id');
}
I'm not being able to get access to publisher and newsTopics when I do something like:
#foreach($posts as $post)
//doesn't work this way
$post->publisher->name;
//nor like this
$publisher->name;
How can I get access to publisher and newsTopics? When I run this controller, it does query what I want but I just don't have access over it.
Any help would be appreciated.
Thank you!
in order to get the model relation you have to load them first in your query:
$posts = Post::with('newsTopics','publisher')->
whereIn('ID', (
NewsTag::
orderBy('post_date','desc')->with('publisher','newsTopics')
->paginate(12)->pluck('post_id')))
->get();
then you can access your relation like:
#foreach($posts as $post)
$publisherName= $post->publisher->name;
more details in:
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading
Is it possible to use an orderBy for an object's related models? That is, let's say I have a Blog Post model with a hasMany("Comments"); I can fetch a collection with
$posts = BlogPost::all();
And then run through each post, and display the comment's last edited date for each one
foreach($posts as $post)
{
foreach($post->comments as $comment)
{
echo $comment->edited_date,"\n";
}
}
Is there a way for me to set the order the comments are returned in?
This is the correct way:
BlogPost::with(['comments' => function ($q) {
$q->orderBy('whatever');
}])->get();
The returned object from the relationship is an Eloquent instance that supports the functions of the query builder, so you can call query builder methods on it.
foreach ($posts as $post) {
foreach ($post->comments()->orderBy('edited_date')->get() as $comment) {
echo $comment->edited_date,"\n";
}
}
Also, keep in mind when you foreach() all posts like this, that Laravel has to run a query to select the comments for the posts in each iteration, so eager loading the comments like you see in Jarek Tkaczyk's answer is recommended.
You can also create an independent function for the ordered comments like you see in this question.
public function comments() {
return $this->hasMany('Comment')->orderBy('comments.edited_date');
}
And then you can loop them like you did in your original code.
Create a JOIN and select just the column you want to order on:
$post = BlogPost::join('comments', function($j) {
$j->on('posts.id', '=', 'comments.post_id');
$j->select('comment_date_or_other_col');
})
->orderBy('comment_date_or_other_col', 'DESC')->first();
Yes:
$posts = BlogPost::with('comments')
->orderBy('comments_table_name.column_name')
->get();
And you can also set that in your relation:
public comments()
{
$this->hasMany("Comments")->orderBy('comments.column_name');
}
I have a model called School and it has many Students .
Here is the code in my model:
public function students()
{
return $this->hasMany('Student');
}
I am getting all the students with this code in my controller:
$school = School::find($schoolId);
and in the view:
#foreach ($school->students as $student)
Now I want to order the Students by some field in the students table. How can I do that?
You have a few ways of achieving this:
// when eager loading
$school = School::with(['students' => function ($q) {
$q->orderBy('whateverField', 'asc/desc');
}])->find($schoolId);
// when lazy loading
$school = School::find($schoolId);
$school->load(['students' => function ($q) {
$q->orderBy('whateverField', 'asc/desc');
}]);
// or on the collection
$school = School::find($schoolId);
// asc
$school->students->sortBy('whateverProperty');
// desc
$school->students->sortByDesc('whateverProperty');
// or querying students directly
$students = Student::whereHas('school', function ($q) use ($schoolId) {
$q->where('id', $schoolId);
})->orderBy('whateverField')->get();
you can add orderBy to your relation, so the only thing you need to change is
public function students()
{
return $this->hasMany('Student');
}
to
public function students()
{
return $this->hasMany('Student')->orderBy('id', 'desc');
}
To answer the original question, the students dynamic property can also be accessed as a relationship method.
So you have this to fetch all students:
$students = $school->students;
Now as a relationship method, this is equivalent:
$students = $school->students()->get();
Given this, you can now add in some ordering:
$students = $school->students()->orderBy('students.last_name')->get();
Since eloquent will be performing a join, make sure to include the table name when referencing the column to order by.
You can also add this to your students method if you want to set a default order that $school->students will always return. Check out the documentation for hasMany() to see how this works.
For Many to one relation I found one answer on:
https://laracasts.com/discuss/channels/eloquent/order-by-on-relationship
$order = 'desc';
$users = User::join('roles', 'users.role_id', '=', 'roles.id')
->orderBy('roles.label', $order)
->select('users.*')
->paginate(10);
this can save day... of anyone
You can use this like this:
$students = $school->students()->orderBy('id', 'desc');
You can also use
$students = $school->students()->orderBy('id', 'desc')->paginate(10);
I have News model, and News has many comments, so I did this in News model:
public function comments(){
$this->hasMany('Comment', 'news_id');
}
But I also have field trashed in comments table, and I only want to select comments that are not trashed. So trashed <> 1. So I wonder is there a way to do something like this:
$news = News::find(123);
$news->comments->where('trashed', '<>', 1); //some sort of pseudo-code
Is there a way to use above method or should I just write something like this:
$comments = Comment::where('trashed', '<>', 1)
->where('news_id', '=', $news->id)
->get();
Any of these should work for you, pick the one you like the most:
Eager-loading.
$comments = News::find(123)->with(['comments' => function ($query) {
$query->where('trashed', '<>', 1);
}])->get();
You can inject the parameter to query function by use($param) method, that allows you to use dynemic query value at runtime.
Lazy-loading
$news = News::find(123);
$comments = $news->comments()->where('trashed', '<>', 1)->get();
I couldn't help but notice, though, that what you're probably trying to do is handle soft deleting, and that Laravel has built-in functionality to help you with that: http://laravel.com/docs/eloquent#soft-deleting
You can do simply in your eloquent model file.
do like this :
public function comments_with_deleted()
{
return $this->belongsTo('Comments', 'id')->where('deleted', 1);
}
public function comments()
{
return $this->belongsTo('Comments', 'id');
}
call like this :
// for show comments with deleted
$comments = News::find(123)->with('comments_with_deleted');
// for show comments without deleted
$comments = News::find(123)->with('comments');
rmobis's answer was what I needed, but it throws an error in current Laravel 5. You have to use it as an associatve array now:
$comments = News::find(123)->with(
['comments' => function ($query) {$query->where('trashed', '<>', 1);}]
);
Took me some time to figure it out, hope this will help others.
Read more in Laravel's Docs (5.6): https://laravel.com/docs/5.6/eloquent-relationships#querying-relations