Grouping related models by pivot - laravel

I'm trying to group related model by pivot data, but this returns only one record of the related for each group. How can I group quiz records by column parent, which is saved in pivot table?
$user = User::where('id', $id)
->with(['quiz' => function($query) use ($md) {
$query->where('md_id',$md)->groupBy('pivot_parent');
}])
->first();

Try this and let me know what did you got
$user= User::where('id', $id)->whereHas('quiz', function($query)
use($md){
$query->where('md_id', '=', $md)-
>groupBy('pivot_parent');
})->first();

Related

Use whereHas and query pivot table

I have 3 table: tasks, users, group, and a pivot table group_user.
A task has user_id, group_id
A group_user pivot table has user_id, group_id
I want to query the tasks if the task belongs to a group of the user.
I don't want tasks from groups that the user doesn't belong to.
What I have so far:
public function index()
{
$userId = Auth::user()->id;
return TaskResource::collection(
Task::
latest()
->whereHas('group', function($query) use($userId) {
$query->where('group_id', '=', $userId); // = is wrong
})
->get()
);
}
This gives me empty results, I tried to think about it but my head hurts
You want to get the tasks that are related to the group (or groups) of a user.
I supposed the relation name between the user table and the group table is 'users', in the Group model.
$userId = auth()->id();
$tasks = Task::latest()
->whereHas('group', function($query) use ($userId) {
$query->whereHas('users', function($query) use ($userId) {
$query->where('user_id', $userId);
});
})
->get();
Ive not tested this but i imagine you could nest the where has and use something like this in your whereHas block:
$query->whereHas('user', function($q2) use ($userId) {
$q2->where('user_id', $userId);
});

laravel eloquent Filter relations Model values with Base Model id

$subTasks = SubTask::with(['task'])
->with(['users.subTaskInfos' => function ($q) {
$q->orderBy('created_at', 'desc');
$q->where('sub_task_id', '=', ?);
}])
->where('active', 1)
->get();
I want to pass Base Model SubTask id in question mark section to filter out relations data and relation collection of data. Can anyone help?
One way to achieve what you are attempting is to lazy eager load users.subTaskInfos - keeping the number of queries the same
$subtasks = SubTask::with(['task'])->where('active', 1)->get();
$subtasks->load(['users.subTaskInfos' => function($q) use($subtasks) {
$q->whereIn('sub_task_id', $subtasks->pluck('id')
->orderByDesc('created_at');
});

Laravel, where, orwhere in main table an pivot table

I have two tables with belongsToMany relation: message_topics and users
The pivot table is message_topics_users and contains 2 columns: message_id and user_id.
In table message_topics, I have a field called sender_id
I'm trying to write the correct eloquent syntax to get all the records:
where message_topics.sender_id = $user_id
OR Message_topics_users.receiver_id = $user_id
I tried many things, like for instance:
$topics = MessageTopic::where('sender_id', $user_id)
->wherePivot('receiver_id', $user_id)->orderBy('sent_at','desc')->get();
Any idea?
You can use the whereHas method (or in this case the orWhereHas method):
$topics = MessageTopic::where('sender_id', $user_id)
->orWhereHas('users', function ($query) use ($user_id) {
$query->where('id', $user_id);
})
->orderBy('sent_at', 'desc')
->get();
I'm assuming you have two relationships from the topics? Since it's too arbitrary to use both columns and the same relationship... Like this
//On your MessageTopic model
public function sender(){
return $this->belongsToMany('App\User', 'message_topics_users', 'message_id', 'sender_id');
}
public function receiver(){
return $this->belongsToMany('App\User', 'message_topics_users', 'message_id', 'receiver_id'));
}
Then you can use whereHas and orWhereHas like this:
//Again assuming you have your User model loaded as $user
$topics = App\Topic::whereHas('sender', function($q) use($user){
$q->where('sender_id', '=', $user->id);
})
->orWhereHas('receiver', function($q) use($user){
$q->where('receiver_id', '=', $user->id
})
->orderByDesc('sent_at')
->get();
whereHas and orWhereHas both query the model (MessageTopic in this case) checking for the existence of the specified relationship (App\Topic::whereHas('sender')...). They also allow you to pass the constraint that you're looking for (function($q) use($user){ $q->... })
So it is basically saying "Give me ONLY the MessageTopics that have a Sender or Receiver with the id $user->id"

Order by related table column

I have a query like:
$users = User::with('role')
->get();
How can I order the results by the related table, so it's something like:
$users = User::with('role')
->orderBy('role.id', 'DESC')
->get();
Is there a way to do it without joining the role table (since we're already doing with('role')?
what are you trying to order. the list of users or the roles.
if you are trying to sort the users base on role do.
$users = User::with('role')->orderBy('role_id', 'DESC')
->get();
if you are trying to sort the roles of the user then pocho's answer is correct.
$users = User::with(array('role' => function($query)
{
$query->orderBy('id', 'DESC');
}))->get();
From the documentation:
$users = User::with(array('role' => function($query)
{
$query->orderBy('id', 'DESC');
}))->get();
You can also do a raw query using DB::raw like in the examples here.
You can always sort the returned collection quite easily...
$users = User::with('role')
->get()
->sortBy(function($user, $key)
{
return $user->role->id;
});
This is assuming a user hasOne or belongsTo a role. If your relationship is something that can return multiple roles, then it becomes a bit more complex because you need to decide which of the user's roles to sort by.

Laravel: how to query to get all records except where relation has name column = admin

I have this query
$users = User::whereHas('roles', function($q){
$q->where('name', '!=', 'admin');
})->get();
but I want to get all users including the ones that have no roles associated. Is there a way to query this?
You want to get the users where the number of roles matching 'admin' is less than one:
$users = User::whereHas('roles', function($q){
$q->where('name', 'admin');
}, '<', 1)->get();
whereHasNot is coming, but not in a release yet.

Resources