Wzorzec pipeline w Laravelu

Dzisiaj poznamy wzorzec pipeline i dowiemy się, jak go używać w Laravelu. PP (Pipeline Pattern) może być zaimplementowany na różne sposoby w każdym języku, ale my zajmiemy się PHP w Laravelu, ponieważ Laravel używa już tego wzorca w swoim rdzeniu.
Czym jest wzorzec pipeline?
Pipeline to wzorzec projektowy zoptymalizowany specjalnie do obsługi skokowych zmian obiektu. Pomyśl o linii montażowej, gdzie każdy krok to rura, a na końcu linii znajduje się przekształcony obiekt.
Istnieje wiele implementacji PP, ale aby lepiej to zobrazować, zaimplementujmy funkcję filtrowania przy użyciu wzorca pipeline i Laravela.
Przykład
Załóżmy, że budujemy system filtrowania w Laravelu. Możemy wyfiltrować Post przy użyciu różnych parametrów, takich jak aktywność lub brak aktywności, sortowanie według ASC lub DESC.
Przed implementacją PP
PostController.php
W metodzie index
stosujemy filtry.
public function index(Request $request)
{
$query = Post::query();
if ($request->has('active')) {
$query->where('active', $request->input('active'));
}
if ($request->has('sort')) {
$query->orderBy('title', $request->input('sort'));
}
/* get filtered data */
$posts = $query->get();
return view('demo', compact('posts'));
}
Wprowadźmy potok filtrów
PostController.php
Aby zaimplementować wzorzec pipeline, musimy dokonać małej refaktoryzacji. Metoda index będzie wyglądała jak poniżej
public function index(Request $request)
{
$posts = app(Pipeline::class)
->send(Post::query())
->through([
\App\Filters\Active::class,
\App\Filters\Sort::class
])
->thenReturn()
->get();
return view('demo', compact('posts'));
}
- metoda
send()
przekaże zapytanie do metody handle. - metoda
through()
pobiera parametry jako klasy, aby przez nie przejść. Mówiąc prościej, jest to lista klas filtrów. -
thenReturn()
zwróci ostateczny output.
Wszystko to jest dostarczane przez Laravela, z wyjątkiem tego, że musimy utworzyć klasy Filter, które są przekazywane w metodzie through().
Klasa Active
Utwórz klasę Active w przestrzeni nazw app/Filters.
namespace App\Filters;
use Closure;
class Active
{
public function handle($request, Closure $next)
{
if (! request()->has('active')) {
return $next($request);
}
return $next($request)->where('active', request()->input('active'));
}
}
Klasa sortująca
Utwórz klasę Active w przestrzeni nazw app/Filters.
namespace App\Filters;
use Closure;
class Sort
{
public function handle($request, Closure $next)
{
if (! request()->has('sort')) {
return $next($request);
}
return $next($request)->orderBy('title', $request->input('sort'));
}
}
To wszystko.
Teraz, jeśli chcę dodać inny filtr, muszę utworzyć nową klasę, powiedzmy Published
, i tę klasę w metodzie through()
, a logikę filtru zaimplementować w metodzie klasy handle
.
Wnioski
Implementacja potoków tylko dla dwóch filtrów może wydawać się trochę przytłaczająca, ale w przypadku dużej liczby filtrów lub innej złożonej implementacji będzie to znacznie korzystniejsze rozwiązanie.
Sortowanie klas filter
PS: Możemy sortować klasy filter, wyodrębniając wspólny kod w klasie bazowej. Do następnego,
Oryginał tekstu w języku angielskim przeczytasz tutaj.