I'm using Laravel 3.x.
Post::with(
array('blogs' => function($query) {
$query->where('user_id', '=', Auth::user()->id);
} ))->get();
How can I paginate the posts?
From the feedback above it seems that eager loading isn't what you are looking for. Try this.
Post::where( 'user_id', '=', Auth::user()->id )->paginate( 10 );
Or you could add a posts method to the User model.
public function posts()
{
return $this->has_many( 'Post' );
}
Then use that to get the users posts.
Auth::user()->posts()->paginate( 10 );
FakeHeal,
Supposing that $user->has_one('blog'), you can simply use Laravel magic relationship getter:
$user = Auth::user();
$user->blog->posts();
If that's not the case and user->has_many('blog'), you need to use JOIN to retrieve all posts made to all of that user blogs.
$user = Auth::user();
$posts = Posts::join('blogs', 'blogs.id', '=', 'posts.blog_id')
->where('blogs.user_id', '=', $user->id)
->get('posts.*');
This is the solution I came up with. A user can have many blogs and a post can belong to many blogs.
/**
* Get all posts by a user for all blogs.
* #return paginated posts.
*/
public static function get_posts_for_user($user_id, $limit)
{
return Post::left_join('blog_post', 'posts.id', '=', 'blog_post.post_id')
->join('blogs', 'blogs.id', '=', 'blog_post.blog_id')
->where('blogs.user_id', '=', $user_id)
->paginate($limit);
}
Related
Having a hard time understanding how to order my Laravel model by a nested relationship.
Here are the Models.
User.php
// Has many small_groups through a pivot table
public function small_groups()
{
return $this->belongsToMany('App\Models\SmallGroup')->withPivot('type')->withTimestamps();
}
SmallGroup.php
// Has many SmallGroupLessons
public function small_group_lessons()
{
return $this->hasMany('App\Models\SmallGroupLesson');
}
SmallGroupLessons.php
// Has many SmallGroupLessonComments
public function small_group_lesson_comments()
{
return $this->hasMany('App\Models\SmallGroupLessonComment');
}
SmallGroupLessonsComment.php
// Belongs to SmallGroupLesson
public function small_group_lesson()
{
return $this->belongsTo('App\Models\SmallGroupLesson');
}
What's I'm trying to do, is pull all of the user's small groups, ordered by the most recent SmallGroupLessonComment if one exists. I've been doing some research, and it sounds like using Laravels ORM in this use case will not work. However, I'm not entirely sure on how to create the join on the nested relationship.
I tried the following, but this only pulls in the most latest SmallGroupLessonComment, however, it does not order the entire result set.
$small_groups = $user->small_groups()->with([
'small_group_lessons' => function($q) {
$q->with([
'latest_comment' => function($q) {
$q->orderBy('created_at', 'asc');
}
]);
}
])->paginate($limit);
Update
Was able to solve it via the following...
$small_groups = $user->small_groups()->with([
'small_group_lessons' => function($q) {
$q->with([
'latest_comment' => function($q) {
$q->orderBy('created_at', 'asc');
}
]);
}
])
->leftJoin('small_group_lessons', 'small_group_lessons.small_group_id', '=', 'small_groups.id')
->leftJoin('small_group_lesson_comments', 'small_group_lesson_comments.small_group_lesson_id', '=', 'small_group_lessons.id')
->orderBy('small_group_lesson_comments.created_at', 'desc')
->paginate($limit);
Update #2
The above doesn't work. I get multiple small groups back that are the same item.
Update #3
This query is pretty close, but it's just ordered by the most recent SmallGroupLesson. Ideally, we order by the SmallGroupLessonComment 🤔
$small_groups = $user->small_groups()->with(
[
'small_group_lessons' => function($q) {
$q->with('latest_comment');
$q->orderBy('created_at', 'desc');
}
],
)
->orderBy(
SmallGroupLesson::select('created_at')
->whereColumn('small_group_id', 'small_groups.id')
->orderBy(SmallGroupLessonComment::select('created_at')
->whereColumn('small_group_lesson_id', 'small_group_lessons.id')
->orderBy('created_at', 'desc')
->limit(1), 'desc')
->limit(1), 'desc'
)
->paginate();
$data=User::select('*')->leftJoin('small_group_lessons','small_group_lessons.user_id','user.id')
->ordeBy('small_group_lessons.created_at','DESC')->get();
try like this
I was able to solve it via the following. Ordering based off the latest comment now works correctly.
$small_groups = $user->small_groups()->with([
'small_group_lessons' => function($q) {
$q->with('latest_comment');
$q->orderBy('created_at', 'desc');
}],
)
->orderBy(
SmallGroupLesson::select('small_group_lesson_comments.created_at')
->join('small_group_lesson_comments', 'small_group_lessons.id', '=', 'small_group_lesson_comments.small_group_lesson_id')
->whereColumn('small_group_id', 'small_groups.id')
->latest()
->limit(1), 'desc'
)
->paginate();
I have one to many relation based two tables users and games and there is also bridge table users_games (linking user_id to games).
I want to fetch a single record from games table based on provided game_id for specific user. I did some research and found whereHas() which is returning all games which are belongs to specific user. But I need to fetch one based on game_id. Can some one kindly let me know how can I fix issue in below script
$GameInfo = User::with('games')->whereHas('games', function ($query) use($request)
{
$query->where('game_id', '=', $request->game_id);
})->find(request()->user()->id);
Is this what you're trying to do?
$GameInfo = $request
->user()
->games()
->where('game_id', $request->game_id)
->first();
try this:
$GameInfo = User::with(['games' => function ($query) use($request)
{
$query->where('game_id', $request->game_id);
}])->whereHas('games', function ($query) use($request)
{
$query->where('game_id', '=', $request->game_id);
})->find(request()->user()->id);
If your relation 'games' is a hasMany() with table 'users_games', You can try this code
$GameInfo = User::with(['games' => function ($query) use($request)
{
$query->where('game_id', $request->game_id);
}])
->where('users.id', <user_id_variable>)
->first();
And the relation 'games' in User Model as
public function games()
{
return $this->hasMany('App\Models\UserGames', 'user_id', 'id');
}
Following is my query
$user = User::with(['session' => function ($query) {
$query->select('id','device_id');
$query->where('api_token', '=', '123456');
}])->get();
session: hasMany relation with User.
I am expecting a user with a session having api_token = 123456. Instead I am getting whole users here. I know I am doing something wrong.
I am referring this doc. In the doc it is saying that we can add constraint to the query. But here $query->where('api_token', '=', '123456'); this where is not working.
You are not filtering the User, you are filtering the result of the eager loading of 'session'. Eager loading does not have any effect on the base result set in anyway.
It sounds like you want to filter User by the 'existence' of a relationship in the database.
User::whereHas('session', function ($q) {
$q->where('api_token', '12345');
})->get(); // ->first();
Get all Users that have a Session where 'api_token' == '12345'.
Laravel 5.5 Docs - Eloquent - Relationships - Querying Relationship Existence
Finally I got it worked.
$sessionSelect = function ($query) {
return $query->select( 'user_id', 'device_id');
};
$detailSelect = function ($query) {
return $query->select('user_id', 'dob', 'gender');
};
$sessionWhere = function ($query) use ($key) {
return $query->where('api_token', $key);
};
$users = User::with(['session' => $sessionSelect,'detail'=>$detailSelect])
->whereHas('session', $sessionWhere)
->first();
I've got a standard many-to-many relationship
class User {
public function roles() {
return $this->belongsToMany('Role');
}
}
class Role {
public function users() {
return $this->belongsToMany('User');
}
}
And it works very well.
But I need to select all the users that has exactly two specific roles.
$roleAdmin = Role::where('name', 'admin')->first();
$roleUser = Role::where('name', 'user')->first();
$users = //which users has BOTH $roleAdmin and $roleUser ??
Is it possible to achieve this using eloquent or I need a raw query?
PS the use-case is stupid, I know, it's just an abstraction of my real problem (that doesn't concern users and roles)
The best solution I found is to get admins and users and then use intersect() helper to get only users who are present both in $users and admins collections:
$users = User::whereHas('roles', function ($q) use($otherRoles) {
$q->where('name', 'user')->whereNotIn('name', $otherRoles);
})->get();
$admins = User::whereHas('roles', function ($q) use($otherRoles) {
$q->where('name', 'admin')->whereNotIn('name', $otherRoles);
})->get();
$result = $admins->intersect($users);
If you want to save some memory, you could pluck() only IDs, intersect() these and only then get users with whereIn().
This is not an eloquent solution(by all means)
$users = \DB::table('users')
->select(\DB::raw("GROUP_CONCAT(roles.name SEPARATOR '-') as `role_names`"), 'users.name')
->join('role_user', 'users.id', '=', 'role_user.user_id')
->join('roles', 'roles.id', '=', 'role_user.role_id')
->groupBy('users.id')
->having('role_names', '=', 'admin-user')
->get();
admin-user can be user-admin, which roles names comes first in the database. Please change table and column names as per your requirement
So i have the table Threads and the table Comments, I want to sort threads by the last comment inserted in something like comments.created_at, how I do this?
$threads = Thread::where('subboaId', $id)
->orderBy('comments.created_at', 'desc')
->get();
tried this but not working maybe I have to join them or something
Use whereHas function (https://laravel.com/docs/5.1/eloquent-relationships) :
First you must add relationship at your Thread model :
public function comments()
{
return $this->hasMany( Comment::class );
}
And then you can use it at your controller like this :
$threads = Thread::where('subboaId', $id)->whereHas( 'comments', function( $query ){
$query->orderBy( 'created_at', 'desc' );
} )->get();
Hope it's helps.
Join them and Try this one,
$threads = Thread::join('comments', 'comments.id', '=', 'threads.comment_id')
->where('threads.subboaId', $id)
->orderBy('comments.created_at', 'desc')
->get();
I hope this will help/lead you.