laravel elequent hasmany with multiple condition - laravel

i want to get users with last messages with another user
users table
id
1
2
messages table
user_id user_reciever_id
1 2
1 2
2 1
2 1
i want get all users that:
messages.user_id=auth::id() and messages.user_reciever_id=users.id
or
messages.user_reciever_id=auth::id() and messages.user_id=users.id
how to handle it with hasmany. thanks alot.

You can do like this =>
public function messages() {
return $this->hasMany('App\Messages', 'user_id' , 'id');
}
public function filteredmessages() {
return $this->messages()->where(// condition)
->where(// condition);
}
$user = User::with('filteredmessages')->get();
print_r($user);
Or you Can use whereHas like this :
$id = auth::id();
$user = User::whereHas('messages', function($q) use ($id){
$q->where('user_id', $id);
$q->where(// additional conditions)
})->get();
Let me know if it helps

Related

How to make a query with relations and order it by date of the relation in Laravel 9

I have the User model, I also have the Post model.
I would like to get 4 users through the newest posts of my entire Post model (taking into account that even a single user could have n number of newest posts) and then get the posts of each user (two for each user) obtained through of the relationship, something like that in case it is not understood very well
I have no problem getting the relationship from the blade, but what I can't get are the 4 users with the newest posts
User model
public function posts()
{
return $this->hasMany(Post::class);
}
Post model
public function user()
{
return $this->belongsTo(User::class);
}
This is the query I was doing, but this will simply return any 4 users (I guess by their id) and each user with their 2 newest posts, which is not what I need
User::query()
->whereHas('posts', function ($query){
$query->where('state', PostStateEnum::PUBLISHED)
->orderBy('updated_at')
->take(2);
})
->take(4)
->get();
ADD:
I have tried with join() but I get the same user
My code:
return User::query()
->join('posts', 'posts.user_id', '=', 'users.id')
->where('posts.state', '=', PostStateEnum::PUBLISHED)
->orderByDesc('posts.updated_at')
->select('users.*')
->with('posts', function ($query) {
$query->where('state', PostStateEnum::PUBLISHED)
->orderByDesc('updated_at')
->take(2)
->get();
})
->take(4)
->get();
that return 4 users, but all are the same user
I found subquery ordering
public function getUsersByNewerPosts()
{
return User::query()
->whereHas('posts', function ($query) {
$query->where('state', PostStateEnum::PUBLISHED);
})
->orderByDesc(
Post::select('updated_at')
->whereColumn('user_id', 'users.id')
->where('state', PostStateEnum::PUBLISHED)
->orderByDesc('updated_at')
->limit(1)
)
->take(4)
->get();
}

laravel Eloquent query WhereHas wrong result

I have two tables and relations as bellow
user
the user table:
id
name
active
1
abc
1
2
xyz
Null
3
abx
0
the book table:
id
user_id
name
active
1
1
book1
0
2
2
book2
0
3
1
book3
0
relation is as this
user->books (HasMany)
return $this->hasMany(Book::class,'user_id','id');
my query is as bellow
User::with('book')
->WhereHas('book', function($query) {
$query->where(['active'=> 1]);
})
->where(['id'=> 1,'active'=>1])
->get();
This query is getting zero records because active is 0 in books
But i want to see all user record and if there is matching record with active 1 in book.
second is query user for active 1 or Null and for that if use ->orwhereNull('active')
All records changes.
Thanks
I guess you need to apply filter on related records (with()) instead of applying filter on whole query. So this way you will always get a list of users along with the list of active books only
User::with(['book'=> function($query) {
$query->where('active', 1);
}])
->where(function ($query) {
$query->where('active', 1)
->orWhereNull('active');
})
->get();
I have used logical grouping here so in case if you have more filter clauses to add in your query.
Or you can define a new relation in your user model to pick only active related books as
class User extends Model
{
public function book()
{
return $this->hasMany(Book::class, 'user_id', 'id');
}
public function active_books()
{
return $this->hasMany(Book::class, 'user_id', 'id')
->where('active', '=', 1);
}
}
User::with('active_books')
->where(function ($query) {
$query->where('active', 1)
->orWhereNull('active');
})
->get();
You have id and active column on both table, so I think you need to change your query like this :
User::with('book')
->WhereHas('book', function($query) {
$query->where(['books.active'=> 1]); // books table active column
})
->where(['id'=> 1,'active'=> 1]) // users table id, active column
->get();

Get values from relationship Laravel

I have a query where I get values from 3 tables, for first 2 I use leftJoin, and is Ok, but for third one I try to get an array of objects, and I am not sure how.
In relationship table a have multiple rows for each ID from People table. HasMany type.
$q = Person::leftJoin('registers', 'people.register_id', '=', 'registers.id')
->leftJoin('relationships', 'people.id', '=', 'relationships.person_id') //if I comment this it works for first 2 tables
->find($id);
return response()->json($q);
Person
public function relationship()
{
return $this->hasMany(Relationship::class);
}
public function register()
{
return $this->belongsTo(Register::class);
}
Relationship
public function person()
{
return $this->belongsTo(Person::class, 'person_id');
}
Register
public function people(){
return $this->hasOne(Person::class);
}
UPDATE -> this works,but is kind of ugly, I think that should be a better way in Laravel
$q = Person::leftJoin('registers', 'people.register_id', '=', 'registers.id')
->find($id);
$q2 = Person::find($id)->relationship;
return response()->json([
'values' => $q,
'relationship' => $q2,
]);
You can just use with like this:
Person::with(['register', 'relationship'])->find($id);

How to get all the user data from another table and include them on user list in laravel?

I am using 2 tables upon displaying my users in my users>index.blade
these 2
USER table
and COLLECTOR_MEMBERS table
The result is this
Now my problem is I want to connect to the other table called
COMMISSIONS table
to achieve this result
MODELS
COMMISSIONS Model
USER
COLLECTOR MEMBER
USER Controller index function
public function index(Request $request)
{
$users = User::all();
$admins = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'admin');
})->get();
$collectorList = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector');
})->with('collectorList')->get();
$borrowers = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'borrower');
})->get();
$userProfile = Auth::user()->id;
if (Auth::User()->hasRole(['borrower','collector'])){
return redirect('dashboard/profile/'.$userProfile);
}
return view('dashboard.users.index', compact('users','profile'))
->with('admins',$admins)
->with('borrowers',$borrowers)
->with('collectorList',$collectorList);
// ->with('collectorBorrowers',$collectorBorrowers);
}
How wan I display the commission_amount column from commissions table? to make my list like this
You could use sum aggregate function, your code should look like this.
$collectorList = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector');
})->with(['collectorCommission' => function($query) {
$query->sum('commission_amount');
}])->get();
Assuming that you have this relationship in your user model
public function collectorCommission() [
return $this->hasMany('App\Commissions', 'user_id');
}
You cant use belongsToMany relationship since this relationship
requires you an intermediary table in your second argument.
You should use hasMany relationship considering that one user has many commissions.

Laravel select posts and comments for active users only

I have three models namely Users, Posts and Comments.
Users table
id username active
1 guyd 1
2 mohok 0
3 cotra 0
Posts table
id post_content user_id
1 Hello 1
2 World 2
3 Foo 3
Comments table
id post_id user_id commment_body
1 1 2 Great post
2 1 3 Totally disagree
3 2 1 Nice read
4 2 3 Wow
5 1 1 Thanks guys
My Posts Model has
public function latestComments($limit = 3)
{
return $this->hasMany(Comment::class)
->where('voided', '=', 0)
->with('user')
->join('users as comment_owner', 'comments.user_id', '=', 'comment_owner.id')
->where('comment_owner.active', '=', 1)
->orderByDesc('comments.updated_at')
->limit($limit);
}
My Comments model has
public function user()
{
return $this->belongsTo(User::class);
}
I want to fetch only posts and comments from users whose active=1. I am using the following but it's giving the wrong results. It's assigning comments to posts without comments.
$posts = Post::orderBy('posts.created_at', 'DESC')
->with('user')
->with('latestComments')
->join('users as post_owner', 'posts.user_id', '=', 'post_owner.id')
->where('active', 1)
->paginate(5);
You should use whereHas()
Post::latest()
->with('user', 'latestComments')
->whereHas('user', function ($q) {
$q->where('active', 1);
})
->paginate(5);
If you also want to filter comments:
->with(['user', 'latestComments' => function ($q) {
$q->whereHas('user', function ($q) {
$q->where('active', 1);
});
}])

Resources