Laravel含OR操作的Query Builder致全局Scope失效问题及解决
Got it, let's tackle this issue head-on. The root problem here is SQL operator priority: AND gets evaluated before OR, so your generated query ends up being interpreted as name like ? OR (id = ? AND user_id = ?) instead of the (name like ? OR id = ?) AND user_id = ? you need.
Here's a robust way to modify your global scope to automatically wrap user-provided query conditions in parentheses, ensuring the correct logic every time:
Modified Global Scope Implementation
protected static function boot() { parent::boot(); static::addGlobalScope('user_filter', function(\Illuminate\Database\Eloquent\Builder $builder) use($userId) { // Capture the original where clauses and bindings from the user's query $originalWheres = $builder->getQuery()->wheres; $originalBindings = $builder->getQuery()->getBindings(); // Clear existing conditions to rebuild the query structure correctly $builder->getQuery()->wheres = []; $builder->getQuery()->setBindings([]); // Wrap the user's original query in a nested where, then add the user_id filter $builder->where(function($subQuery) use ($originalWheres, $originalBindings) { // Restore the user's original query conditions $subQuery->getQuery()->wheres = $originalWheres; $subQuery->getQuery()->setBindings($originalBindings); })->where( (new static)->getTable() . '.user_id', '=', $userId ); }); }
How This Works
- Capture Original Conditions: We first grab all the existing
WHEREclauses and their bindings that the user added (like yourwhereRawOR query). - Reset the Builder: Clear out the current conditions so we can rebuild the query with the correct structure.
- Rebuild with Nested Where: We wrap the user's original query inside a nested
WHEREclosure (which automatically adds the necessary parentheses) and then chain ouruser_idfilter onto it. The final generated SQL will look exactly like you need:select * from `cars` where (name like ? or id = ?) and user_id = ?
Why This Is Better Than Manual Fixes
This approach eliminates the need to manually add parentheses to every query that uses OR conditions. It works seamlessly with raw queries, chained where calls, and complex conditional logic—you don't have to worry about remembering to adjust individual queries.
内容的提问来源于stack exchange,提问作者tomloprod

