Tim Lewis
Tim Lewis

Reputation: 29278

PHP Laravel Query Cloning Not Working as Expected

So I'm coming across an issue with QueryBuilder cloning. He's my situation, I need to run 3 separate queries, all based off a single "BaseQuery":

$baseQuery = $model->selectRaw("column")->whereNull("deleted_at");

$query1 = clone($baseQuery);
$query1Results = $query1->where("condition", "=", 0)->get();

$query2 = clone($baseQuery);
$query2Results = $query2->where("condition2", "=", 1)->get();

$query3 = clone($baseQuery);
$query3Results = $query3->where("condition3", "=", 0)->get();

By the time I get to $query3, it has 3 where statements. Substituting $query3 ... get() with $query3 ... ->toSql(); shows these results:

SELECT `column` FROM `models` WHERE `deleted_at` IS NULL AND `condition` = ? AND `condition2` = ? AND `condition3` = ?;

It seems that even though I am defining each $queryX as a clone of $baseQuery, the additional ->where() clause is being applied to each of the queries. I've tried doing the clone() before appending any of the ->where() clauses, but that doesn't have any affect.

Is there a way to clone() something and ensure that it creates a new instance? It looks like clone() isn't separating $baseQuery from $queryX, so the ->where()s are being applied to every subsequent copy, even though each should be a new query with only the ->whereNull() clause.

Another interesting point is that running

\Log::info($baseQuery == $queryX);

After each modification returns true (=== is false though)

Upvotes: 1

Views: 337

Answers (1)

Alexey Mezenin
Alexey Mezenin

Reputation: 163788

You should use scopes here.

Local scopes allow you to define common sets of constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered "popular". To define a scope, simply prefix an Eloquent model method with scope

public function scopeBase($q)
{
    return $q->selectRaw('column')->whereNull('deleted_at');
}

Then just do something like this:

$query1Results = $model->where('condition', 0)->base()->get();
$query2Results = $model->where('condition2', 1)->base()->get();
$query3Results = $model->where('condition3', 0)->base()->get();

Upvotes: 1

Related Questions