I came across a small edge-case when using Laravel's Global Scopes after following the example in the documentation.
I created an "Active" scope, which can be applied to multiple models.
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model): void
{
$builder->where('active', '=', 1);
}
}
This scope is simple enough and worked well. However, I came across an SQL error when I was using a "through" relationship, for example hasOneThrough
or hasManyThrough
, when two models both used the global active scope.
The problem was the query that was generated contained active = 1
. When this is used with a join table, the resulting query did not know which table the active
column should be used.
1052 Column 'active' in where clause is ambiguous
Thankfully there was a relatively easy and quick fix for this and that was to use the qualifyColumn()
method provided by the model which is applying the global scope. This prefixes the column with the model's table name and solves the ambiguous clause.
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model): void
{
$builder->where($model->qualifyColumn('active'), '=', 1);
}
}