Laravel Eloquent Global Scope | EspecializaTi
Por: Carlos Ferreira 25/06/2018	 Comentar
Laravel Eloquent Global Scope
No último tutorial detalhei sobre Local Scopes no Laravel, agora dando continuidade ao tutorial vou abordar sobre Global Scopes no Laravel.
Diferente do Local Scope que é aplicado manualmente na query, o Global Scope é aplicado por default (padrão). O recurso de Soft Deleting é aplicado por padrão devido ao recurso de Global Scope.
Em que cenário usar o Global Scope?
Vamos imaginar que temos uma tabela products (produtos), que tem diversas colunas com as informações do produto, e ainda tem uma coluna adicional chamada por exemplo "visible", que é do tipo Boolean, e por default (padrão) o valor é "true" (visível).
No sistema precisamos exibir apenas os produtos visíveis, poderíamos criar um Local Scope para resolver isso, mas, neste caso precisaríamos em todos os momentos que fosse selecionar os produtos vincular a query com o Local Scope, ficaria trabalhoso. O Global Scope resolve este caso, porque podemos definir que uma ou mais condições sejam aplicadas automaticamente.
Dentro do diretório app/ do Laravel, crie um novo diretório chamado Scopes, é neste diretório pode podemos salvar todos os Global Scopes.
Dentro de app/Scopes/ crie um arquivo e classe chamado VisibleScope.
"Visible" é o nome da funcioalidade, e "Scope" é interessante prefixar no nome da Classe para identificar o recurso.
Na classe VisibleScope crie um método apply(), para aplicar o filtro (where) default (padrão). Essa classe deve herdar de Illuminate\Database\Eloquent\Scope. Exemplo:
class VisibleScope implements Scope
$builder->where('visible', true);
O método apply() injeta duas classes: Illuminate\Database\Eloquent\Builder que serve para aplicar as querys e Illuminate\Database\Eloquent\Model que é o objeto da Model, que pode ser usado para talvez aplicar uma query diferente para um Model específico.
Neste exemplo aplicamos um where() para filtrar os dados cuja a coluna visible seja true.
Se quiser aplicar mais de um where() pode encadear, algo assim:
$builder->where('visible', true)
->where('price', '>', 0);
Aplicando Global Scopes
Uma vez que foi criado o nosso Global Scope, podemos aplicar em quantos Models for necessário aplicar o filtro default.
Para isso você deve fazer o override (Polimorfismo) do método estático boot(), assim:
use App\Scopes\VisibleScope;
static::addGlobalScope(new VisibleScope);
No método boot() chamamos o método boot() principal (PAI) com:
E para aplicar o Scope Global bastou usar o método estático addGlobalScope() passando um objeto do nosso Global Scope App\Scopes\VisibleScope;
Agora quando fizer uma consulta através do Model Product automaticamente vai aplicar os filtros definidos no Global Scope VisibleScope
$product = Product::get(); // Product::all();
// Query: select * from `products` where `visible` = 1
Para debugar a query, faça o teste:
dd(Product::toSql());
Agora se precisa aplicar o conceito de Global Scope em um Model particular, sem a necessidade de reaproveitar, não em a necessidade de criar uma classe para aplicar a finalidade, pode reescrever (override) o método boot() aplicando o filtro default:
Desta vez no método addGlobalScope() invés de passar um objeto do Global Scope passamos um nome de identificação "visible" + uma função de callback aplicando a query exclusiva de default (padrão) do Model.
Remover Global Scopes
Uma das possibilidades do Eloquent é excluir um Scope Global aplicado. Essa opção é interessante por exemplo em caso de ter que listar os produtos no site (com Scope Global), porém no painel de administração listar todos os produtos, sem filtro.