Laravel Divided Query Overwrites Previous Variable

What I am trying to achieve is to create a query and use it with multiple endings:

For example

$query = User::where('is_admin', true);

if ($query->where('badge', 'red')->exists())
{
  //do something
}

if ($query->where('badge', 'green')->exists())
{
  //do something
}

$query->get();

$query->first();

With this, the $query variable gets overwritten every time the query is finished therefore it is not possible to re-use $query;

The current solution I have is utilizing clone

$query = User::where('is_admin', true);

$query1 = clone $query;
if ($query1->where('badge', 'red')->exists())
{
  //do something
}

$query2 = clone $query
if ($query2->where('badge', 'green')->exists())
{
  //do something
}

$query3 = clone $query;
$query3->get();

$query4 = clone $query;
$query4->first();

The example is used just to get the point across, not a real
life scenario.

I guess it works and does what I want, just does not feel like a laravel way of doing something, quite verbose and it gets worse with more complicated logic.

The goal is to re-use the same variable without overwriting it every time I finalize the query.

Does anybody have a better solution to this?

Is there a way to somehow break the reactivity of the $query variable?

Thanks

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

An elegant option is to make use of Laravel Local Query Scopes.

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class User extends Model
{
    /**
     * Scope a query to only include administrators.
     *
     * @param  IlluminateDatabaseEloquentBuilder  $query
     * @return IlluminateDatabaseEloquentBuilder
     */
    public function scopeAdmins($query)
    {
        return $query->where('is_admin', true);
    }

  
}

Now, to utilize the newly created local scope:

if (User::admins()->where('badge', 'red')->exists())
{
  //do something
}

if (User::admins()->where('badge', 'green')->exists())
{
  //do something
}

Method 2

For starters, $query doesn’t sound like a good name for fetching Users that are admins.

so, let’s quickly change it so it’s more clear for us to read and think

$user_admins = User::where('is_admin', true);

if ($user_admins->where('badge', 'red')->exists())
{
  //do something
} 

if ($user_admins->where('badge', 'green')->exists())
{
  //do something
}

okay, so we grabbed admins, let’s iterate through them with a foreach loop
$user_admins = User::where('is_admin', true);

foreach($user_admins as $admin) {
    if ($admin->badge == 'green') {
         // do something
    } else if ($admin->badge == 'red') {
        // do something else
    }
}

now, whenever you change the $admin variable inside the loop, it will change that individual admin.

also query is the “question” eloquent is “asking” the database (for example: “SELECT * FROM users WHERE is_admin=true”; so query does not not refer to the result.

note you could also use a switch statement if you have a lot of logic, it would look like this:

$user_admins = User::where('is_admin', true);

foreach($user_admins as $admin) {
    switch($admin->badge) {
        case 'green:
            // do something
            break;
        case 'red:
            // do something else
            break;
        case 'ltblue:
        case 'blue:
            // do same things for ltblue and blue
            break;
        default: break;
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x