maxboychuk14 May 2026 11:47

I see a lot of code that adds the same where conditions in three different controllers. Query scopes exist to fix exactly that, but the tradeoff is not always obvious. Here is a concrete comparison.

The same concept works in Hyperf ORM which uses the same API as Eloquent. Run the logic part in sandbox to understand the scope mechanics:

PHP
<?php
// Simulate what Eloquent scopes do conceptually
// (Actual Eloquent requires a DB connection, this shows the pattern)
class QueryBuilder
{
private array $conditions = [];
private ?int $limitVal = null;
public function where(string $field, mixed $value): static
{
$this->conditions[] = "$field = " . (is_string($value) ? "'$value'" : $value);
return $this;
}
public function limit(int $n): static
{
$this->limitVal = $n;
return $this;
}
public function toSql(): string
{
$sql = "SELECT * FROM users";
if ($this->conditions) {
$sql .= " WHERE " . implode(" AND ", $this->conditions);
}
if ($this->limitVal !== null) {
$sql .= " LIMIT {$this->limitVal}";
}
return $sql;
}
}
// Simulated scopes as methods
class UserQuery extends QueryBuilder
{
public function active(): static
{
return $this->where('status', 'active');
}
public function verified(): static
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Scopes make sense the moment you use the same condition in more than one place. One change in the scope method fixes all call sites simultaneously.

Replies (2)
sergey_web14 May 2026 12:18

The real benefit shows up during refactors. We had where('deleted_at', null)->where('status', 'active') scattered across 20 controllers. When the business added a “suspended” status that should also be excluded, we had to grep the whole codebase.

After moving to scopes, that change was one line in one method. The controllers did not need to know about the internal status logic at all.

One gotcha with Hyperf specifically: scopes defined with scope prefix work the same as in Laravel, but global scopes require registering in boot() via the model observer pattern which is slightly different from the Laravel booting() static method.

0
irynaDev14 May 2026 15:43

Counter-point: scopes can hide complexity. When a junior developer calls ->active() and gets unexpected results because the scope has six conditions internally including joins, debugging is harder than with a visible where chain.

I use scopes for simple reusable filters and keep complex multi-table conditions in repository methods with explicit names like findActiveVerifiedWithRecentOrders(). The name communicates what it does, and the implementation is readable in one place.

0
Write a reply
Markdown. ```php blocks are runnable.