Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Eloquent - Where In All

In Laravel 4.2, I am trying to achieve a query that returns all users, that have all of certain activities. As of now, I have a query that returns all users that have one of many activities:

//$selectedActivities being an array
        $userByActivities = User::with('activities')
                ->whereHas('activities', function($query) use($selectedActivities){
                    $query->whereIn('id', $selectedActivities);
                })->get();

To be more clear: given activities a,b,c. I am looking for all users that have activity a AND b AND c. My query returns all users that have activity a OR b OR c.

Thank you for your help.

EDIT:

The solution offered by lukasgeiter results in following query:

select * from `users` where 
        (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '7') >= 1 
        and (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '3') >= 1 
        and (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '1') >= 1 
        and (select count(*) from `activities` inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` where `activity_user`.`user_id` = `users`.`id` and `id` = '2') >= 1

Whereas the solution offered by Jarek Tkaczyk:

$userByActivities = User::with('activities')
 ->whereHas('activities', function($query) use($selectedActivities) {
     $query->selectRaw('count(distinct id)')->whereIn('id', $selectedActivities);
 }, '=', count($selectedActivities))->get();

for a similar request, results in following query:

select * from `users` where (select count(distinct id) from `activities` 
    inner join `activity_user` on `activities`.`id` = `activity_user`.`activity_id` 
    where `activity_user`.`user_id` = `users`.`id` and `id` in ('7', '3', '1', '2')) = 4
like image 619
musaya Avatar asked Feb 20 '15 16:02

musaya


People also ask

What is all () in Laravel?

all() is a static method on the Eloquent\Model. All it does is create a new query object and call get() on it. With all(), you cannot modify the query performed at all (except you can choose the columns to select by passing them as parameters). get() is a method on the Eloquent\Builder object.

What is the difference between GET and all in Laravel 8?

get() is used when you want to add queries and all() is used to get all data, without using any condition.

What does get () do in Laravel?

For creating ::where statements, you will use get() and first() methods. The first() method will return only one record, while the get() method will return an array of records that you can loop over. Also, the find() method can be used with an array of primary keys, which will return a collection of matching records.

What is fillable in Laravel?

The fillable property is used inside the model. It takes care of defining which fields are to be considered when the user will insert or update data. Only the fields marked as fillable are used in the mass assignment. This is done to avoid mass assignment data attacks when the user sends data from the HTTP request.


2 Answers

You'll have to add multiple whereHas for that:

$query = User::with('activities');
foreach($selectedActivities as $activityId){
    $query->whereHas('activities', function($q) use ($activityId){
        $q->where('id', $activityId);
    });
}
$userByActivities = $query->get();
like image 143
lukasgeiter Avatar answered Jan 02 '23 00:01

lukasgeiter


If you are getting Cardinality violation: 1241 Operand should contain 2 column(s) the problem is the nested selectCount adds to the normal select count(*) instead of overriding the existing select, so changing to $query->distinct()->whereIn('id', $selectedActivities); did the trick for me, or changing to $query->select(DB::raw(count(distinct id)))

like image 42
Victor Priceputu Avatar answered Jan 02 '23 01:01

Victor Priceputu