If you had a global scope attached to a model in Laravel and it worked like clockwork, until suddenly it got lost or broke in a new function, check whether you're using raw methods. For example, whereRaw() or orderByRaw() in that new function.
A Global Scope is a class where you can define conditions once and then have them applied automatically to all Eloquent queries of a given model (that is, to queries via
Model::). For example, you can write a global scope that limits models by author, so that->where('user_id', '=', Auth::user()->id)is automatically added to any query likeOrder::all().
So, it turns out that a global scope is sensitive to "raw" queries. That doesn't mean you can't use them together, you can. The thing is, the query builder doesn't isolate "raw" conditions from "normal" ones. And if, for example, you have a condition like this in whereRaw():
(DAYOFYEAR(date_of_birth) - DAYOFYEAR(?) BETWEEN 0 AND 30) OR (DAYOFYEAR(date_of_birth) - DAYOFYEAR(?) BETWEEN -365 AND -335)
then the builder won't add any parentheses for you and will attach the condition from the scope as is:
(DAYOFYEAR(date_of_birth) - DAYOFYEAR(?) BETWEEN 0 AND 30) OR (DAYOFYEAR(date_of_birth) - DAYOFYEAR(?) BETWEEN -365 AND -335) AND (user_id = 3)
and as you can easily see, the order in which the conditions are evaluated here won't be at all what we intended.
The solution, as is now obvious, is simple: whenever you need to use whereRaw(), wrap the entire condition in parentheses.
Or you can go further: rewrite the builder class so that it adds parentheses in whereRaw() automatically, and tell your models to use this new builder. Like they did here.
P.S. Actually, the same thing can happen if you simply use whereRaw() and where() together. So, watch your parentheses.