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
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));
}
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.
I know this has been asked before but specific to my case I could't find an answer that worked.
Currently I have two models.
App\JobStatus
App\Customer
In model App\JobStatus I have this:
public function customer()
{
return $this->belongsTo('App\Customer');
}
In model App\Customer I have this:
public function jobs()
{
return $this->hasMany('App\JobStatus', 'customer_id');
}
'customer_id' is the foreign key. I then try to access customer from Jobstatus in my controller like so:
$testMePlease = JobStatus::first()->where('qb', '=', 1);
$testMePlease->customer;
I have attempted to dd this. To put it in foreach loop. I've also tried $testMePlease->customer->customer_name. Customer_name being a column in the table and I get back the same error: "Undefined property: Illuminate\Database\Eloquent\Builder::$customer"
Any ideas what I'm doing wrong?
Try to change
$testMePlease = JobStatus::first()->where('qb', '=', 1);
To
$testMePlease = JobStatus::where('qb', '=', 1)->first();
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 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