Paginate Laravel Relation - laravel

I have two tables let's say posts and comments with Post and Comment Model.
Post.php
public function comments(){
return $this->hasMany(Comment::class);
}
Comment.php
public function post(){
return $this->belongsTo(Post::class);
}
Now I want to load Post with comments with pagination on both Post and comments.
What I tried so far,
Post::with('comments')->pagenate();
The above code only paginates on Post Model. So I tried the following code but no luck.
In Post.php
public function comments(){
return $this->belongsTo(Comment::class)->paginate(5);
}
Post::with('comments')->pagenate();

In the controller you must put the Post variable and for each post the Comments variable with it paginate, then you return the variables.
$posts = Post::orderBy('id', 'desc')->paginate(10);
foreach ($posts as $post)
$comments = $post->comments()->paginate(2);
return view('post.index', ['posts' => $posts, 'comments' => $comments]);
Now, in the blade view, you only need to put the #foreach of the comments variable in the post and add the links to page it for you.
#foreach( $comments as $comment )
<p> {{ $comment->desc }}</p>
#endforeach
{{ $comments->links() }}

Related

Laravel: Passing data to view through route after querying

I recently asked a question about defining many to many relationships (using belongsToMany) and it was a huge help. So now in my models I have:
Users model
public function subjects()
{
return $this->belongsToMany('App\Subject', 'users_subjects', 'user_id', 'subjects_id');
}
Subjects model
public function users()
{
return $this->belongsToMany('App\User', 'users_subjects', 'subject_id', 'user_id');
}
This way I establish a relationship between users and subjects via the users_subjects table. My next step was to create a controller, SubjectsController, which ended up looking like this:
class SubjectsController extends Controller
{
// returns the view where subjects will be displayed
public function index()
{
return view('profiles.professor.prof_didactic_subjects');
}
// get users with subjects
public function getSubjects()
{
$subjects = User::with('subjects')->get();
}
// get a single user with a subject
public function getSubject($id)
{
$materia = User::where('id', '=', $id)->with('subjects')->first();
}
}
I'm not very sure about the code in the controller though.
The final step is where it gets tricky for me, even after reading the docs: I want to pass each result to the view, so I can have multiple tiles, each populated with data from subjects the user is associated with:
#foreach ($subjects as $subject)
<div class="tile is-parent">
<article class="tile is-child box">
<p class="title">{{ $subject['name'] }}</p>
<div class="content">
<p>{{ $subject['description'] }}</p>
</div>
</article>
</div>
#endforeach
I tried many different route configurations, but kept getting either the undefined variable error or trying to access non-object error.
What's the proper course of action here? I feel I'm missing something very basic. Thanks in advance for any help.
The answer
The solution provided below by #Sohel0415 worked perfectly. My index() method on the controller now looks like this:
public function index()
{
// temporary value while I figure out how to get the id of the current user
$user_id = 6;
$subjects = Subject::whereHas('users', function($q) use ($user_id){
$q->where('user_id', $user_id);
})->get();
return view('profiles.professor.prof_didactic_subjects')->with('subjects', $subjects);
}
My route looks like this:
Route::get('/professor', 'SubjectsController#index');
I was pretty lost, so this absolutely saved me, thanks again :)
You need to pass $subjects to your view. You can use compact() method for that like -
public function index()
{
$subjects = Subject::with('users')->get();
return view('profiles.professor.prof_didactic_subjects', compact('subjects'));
}
Or using with() method like -
public function index()
{
$subjects = Subject::with('users')->get();
return view('profiles.professor.prof_didactic_subjects')->with('subjects', $subjects);
}
If you want to get Subject for a particular user_id, use whereHas() -
$subjects = Subject::whereHas('users', function($q) use ($user_id){
$q->where('user_id', $user_id);
})->get();

Laravel 5 how paginate with hasMany relationship

I have a relationship this like;
public function foods() {
return $this->hasMany('App\models\food\food', 'category_id', 'id');
}
My controller file content;
$datas = food_category::where('slug', $slug)->with('foods')->paginate(12);
But incoming datas in there all datas and this is causing bad performance. I want to paginate apply relationship datas.
If you want to paginate foods, try adding a separate method for that:
Model:
class food_category
{
public function getFoodsPaginatedAttribute()
{
return $this->foods()->paginate(12);
}
}
Controller:
$datas = food_category::where('slug', $slug)->get();
View:
#foreach ($datas as $data)
#foreach ($data->foods_paginated as $food)
{{ $food->name }}
#endforeach
#endforeach
Pass paginated collection to the view:
//view
#foreach ($datas as $data)
// do what you need
#endforeach
//link
{{$datas->links()}}

How to retrieve user name from user table by using data (user_id) from another table having relationship

I have two models
User.php
public function opportunities()
{
return $this->hasMany('App\Opportunity');
}
Opportunity.php
public function user()
{
return $this->belongsTo('App\User');
}
I have user_id column in opportunities table and inserted user id (from user table using Auth) every time user posts record.
Now i need a view to return "this post is posted this user".
First I find the post id by
$posts = Opportunity::find($id);
$posted_by = User::find($posts->user_id);
return view('opportunity.detail')->with('post', $posts, 'posted_by', $posted_by);
I have rendered user name by {{$posted_by->name}}
But I got undefined constant in the view file $posted_by while $post is fine. Am I doing it in right way or not? I am passing two array variable to the post and its not working. Any help will be appreciated.
Your controller could look like:
return view('opportunity.detail', [
'post' => Opportunity::find($id);
]);
In the view to show user name:
Post {{ $post->title }} posted by {{ $post->user->name }}
https://laravel.com/docs/5.5/eloquent-relationships#relationship-methods-vs-dynamic-properties
If for some reason you want to use ->with(), do this:
->with(['post' => $posts, 'posted_by' => $posted_by]);
Or:
->with('post', $posts)->with('posted_by', $posted_by);
You can put this
public function getUserName() {
return User::where('id', $this->user_id)->first()->name;
}
in your Opportunity.php model and call it in you view
#foreach ($posts as $post)
{{ $post->getUserName() }}
#endforeach

Laravel orderBy Not Passing to View

I am pulling a collection from my database table using the following code.
$profileVisits = DB::table('recently_visited')
->where('visitor_id',Auth::user()->id)
->orderBy('times_visited', 'desc')->get();
return view('profile.index')
->with([
'user' => $user,
'posts' => $posts,
'profileVisits' => $profileVisits,
]);
When I dd($profileVisits) it shows the collection with the correct descending results. However, when I pull the info into my view using the following code, it doesn't descend like it's supposed to. Is the orderBy query builder being undone or something with the "return view..." code?
Code in view...
#if (!$user->profileVisits->count())
#else
#foreach ($user->profileVisits as $topVisits)
<p>{{ $topVisits->getUsername() }}</p>
#endforeach
#endif
User Model:
public function profileVisits()
{
return $this->BelongsToMany('App\Models\User', 'recently_visited', 'visitor_id', 'profile_id');
}
public function addProfileVisits(User $user)
{
$this->profileVisits()->attach($user->id);
}
public function previouslyVisited(User $user)
{
return (bool) $this->profileVisits()->get()->where('id', $user->id)->count();
}
Actually, I just figured it out. On the User Model, I added the orderBy instead of using it in the Controller. See below.
User Model:
public function profileVisits()
{
return $this->BelongsToMany('App\Models\User', 'recently_visited', 'visitor_id', 'profile_id')->orderBy('times_visited', 'desc');
}

Laravel eloquent grab user with posts ordered by

I am playing around with Laravel and I have this code. It returns all of a users posts, based on the provided username.
Controller
$posts = User::whereUsername($username)->firstOrFail()->posts;
return View::make('users.index')->with($posts);
View
#foreach($posts as $post)
{{ $post->title }}
{{ $post-owner->username }}
// etc etc
#endforeach
How would I go about adding an orderBy() to my query? I would like the posts to be ordered by newest first. This was my attempt :(
User::whereUsername($username)->firstOrFail()->posts->orderBy('created_at', 'DESC');
Or is there a better way to go about doing this?
EDIT
User Model
public function posts()
{
return $this->hasMany('Post');
}
Post Model
public function owner()
{
return $this->belongsTo('User', 'user_id');
}
Your code is slightly missing the () brackets on the relationship!
Try this
User::whereUsername($username)
->firstOrFail()
->posts()
->orderBy('created_at', 'DESC')
->get();
Note the brackets on posts()->

Resources