简体   繁体   中英

Is there any way to get two different results with single query based on condition?

I am trying to get two different results from single query but the problem is both conditions get applied on last query.

for example

$getUser = User::join('role_user','role_user.user_id','users.id')
        ->select('users.id','users.name','users.email','users.identity_status','users.email_verified_at','role_user.role_id')
        ->where('role_user.role_id',2)
        ->whereNotNull('users.email_verified_at');

$newMailUsers = $getUser->where('new_mail',0)->get();
            
$topSellingMailUsers = $getUser->where('topselling_mail',0)->get();

but when i checked sql query of $topSellingMailUsers i saw that both the conditions of new_mail and topselling_mail applied in $topSellingMailUsers query what i want is it should not consider mail condition in query.

how can i get two different results of $newMailUsers, $topSellingMailUsers based on both conditions separately.

Every time you use where() method you are mutating $getUser query builder.

You can chain your query builder with clone() method and this will return another query builder with the same properties.

$getUser = User::join('role_user','role_user.user_id','users.id')
        ->select('users.id','users.name','users.email','users.identity_status','users.email_verified_at','role_user.role_id')
        ->where('role_user.role_id',2)
        ->whereNotNull('users.email_verified_at');

$newMailUsers = $getUser->clone()->where('new_mail',0)->get();
            
$topSellingMailUsers = $getUser->clone()->where('topselling_mail',0)->get();

you need to clone Builder object to reuse it

$selectFields = [
  'users.id', 
  'users.name', 
  'users.email', 
  'users.identity_status', 
  'users.email_verified_at', 
  'role_user.role_id'
];
/** @var Illuminate\Database\Eloquent\Builder */
$getUser = User::join('role_user', 'role_user.user_id', 'users.id')
  ->select($selectFields)
  ->where('role_user.role_id', 2)
  ->whereNotNull('users.email_verified_at');

$newMailUsers = (clone $getUser)->where('new_mail', 0)->get();

$topSellingMailUsers = (clone $getUser)->where('topselling_mail', 0)->get();

Well, if you have relations set up on models will be easier, but still can do it:

// Let's say you pass sometimes the role_id
$role_id = $request->role_id ?? null;
        
$getUser = User::join('role_user','role_user.user_id','users.id')
   ->select('users.id','users.name','users.email','users.identity_status','users.email_verified_at','role_user.role_id')
   // ->where('role_user.role_id',2) // replaced with ->when() method
   ->when($role_id, function ($query) use ($role_id){
       $query->where('role_user.role_id', $role_id);
   })
   ->whereNotNull('users.email_verified_at');

This way it will return users with ALL ROLES or if ->when(condition is TRUE) it will return users with the role id = $role_id.

You can use multiple ->when(condition, function(){});

Have fun!

Instead of firing multiple queries you can do it in a single query as well by using collection method as like below.

$users = User::join('role_user','role_user.user_id','users.id')
    ->select('users.id','users.name','users.email','users.identity_status','users.email_verified_at','role_user.role_id', 'new_mail', 'topselling_mail')
    ->where('role_user.role_id',2)
    ->where(function($query) {
       $query->where('new_mail', 0)->orWhere('topselling_mail', 0);
    })
    ->whereNotNull('users.email_verified_at')
    ->get();

$newMailUsers = $users->where('new_mail',0)->get();
        
$topSellingMailUsers = $user->where('topselling_mail',0)->get();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM