Laravel advanced: Tappable scopes

Bastiaan Dewaele
2 min readOct 10, 2023
Photo by Ben Griffiths

Laravel has lesser known features such as Tappable scopes, which basically defines Eloquent scopes in a separate PHP-class.

What I am going to demonstrate isn’t defined anywhere at the official documentation website.

Typical example of defining a local scope

While we normally define scopes by adding a method under a specific model.

<?php

class GuineaPig {
pubic function scopeIsHungry(Builder $builder) {
$builder->where("last_meal_at", '>', now()->subMinutes());
}
}

$query = GuineaPig::query()->isHungry()->get(); // OR
$query = GuineaPig::query()->scopes(['isHungry'])->get();

We can see the presence of a publicly accessible method called scopeIsHungry. To utilize this scope, we would write code in the following manner.

This feature proves to be helpful; however, it can lead to subpar code suggestions from the editor. It’s important to keep that in mind, because without code suggestions it’s up to the user to review and determine breaking changes.

  • Editors like PhpStorm won’t detect breaking name changes, when renaming the method scopeIsHungry.
  • Some editors may express frustration about the unused method scopeIsHungry(). Caution is advised when removing that method, as it may affect a large amount of code.
  • Once you use the scopeIsHungry() method, it returns zero for auto-completion. This means that there are no suggestions or options available for further completion.

Alternative solution: tappable scopes

The better solution is moving the code to its own invokable PHP-class.

<?php 

class IsHungryTap {
public function __invoke(Builder $builder): void
{
// https://ownyourpet.com/why-are-guinea-pigs-always-hungry/
$builder->where("last_meal_at", '>', now()->subMinutes(15));
}
}

And it can easily be implemented by using the method tap when using a builder.

<?php

$query = GuineaPig->query()->tap(new IsHungryTap())->get();

Compared to the original example, you get decent code-hinting by your editor when you search for usages.

Summary:

  • Find usages of IsHungryTap
  • Better code-hinting inside your code editor
  • Isolate the local scope to its own PHP-class, to make the model less bloated

Sources

--

--

Bastiaan Dewaele

Senior back-end developer in Ghent who likes writing sometimes weird / creative solutions to a specific problem.