Laravel — фреймворк, который любит порядок. Один из инструментов, который помогает наводить порядок в коде, — Pipeline.
Проблема в том, что Pipeline часто объясняют сложно: через паттерны, абстракции и термины, из-за чего новичкам вообще непонятно — зачем он нужен и где его применять.
В этой статье разберём Pipeline очень просто, на реальном примере с Livewire, без сложной теории.
Что такое Pipeline простыми словами
Pipeline — это цепочка шагов.
Ты берёшь какой-то объект (данные, запрос, форму)
и пропускаешь его через несколько обработчиков по очереди.
Каждый шаг:
- получает данные
- что-то с ними делает
- передаёт дальше
Как конвейер на заводе:
- Проверили
- Подготовили
- Сохранили
- Вернули результат
Проблема, с которой сталкивается каждый новичок
Представим Livewire-компонент с формой регистрации.
❌ Плохой (но очень частый) вариант:
public function save()
{
if (strlen($this->name) < 3) {
$this->addError('name', 'Имя слишком короткое');
return;
}
if (! filter_var($this->email, FILTER_VALIDATE_EMAIL)) {
$this->addError('email', 'Неверный email');
return;
}
$this->email = strtolower($this->email);
User::create([
'name' => $this->name,
'email' => $this->email,
]);
}
Что здесь не так:
- логика растёт
- всё свалено в один метод
- невозможно переиспользовать код
- сложно тестировать
Именно здесь Pipeline начинает быть полезным.
Идея Pipeline на этом примере
Вместо одного большого метода мы сделаем:
- Проверку данных
- Подготовку данных
- Сохранение пользователя
Каждый шаг — отдельный класс
Подготовим Livewire-компонент
use Livewire\Component;
use Illuminate\Pipeline\Pipeline;
class RegisterForm extends Component
{
public string $name = '';
public string $email = '';
public function save()
{
app(Pipeline::class)
->send($this)
->through([
Pipelines\ValidateForm::class,
Pipelines\NormalizeEmail::class,
Pipelines\CreateUser::class,
])
->thenReturn();
}
public function render()
{
return view('livewire.register-form');
}
}
Обрати внимание:
- мы передаём весь компонент в Pipeline
- шаги идут строго по порядку
- метод
save()стал очень чистым
Как выглядит шаг Pipeline
Шаг 1. Валидация формы
namespace App\Pipelines;
use Closure;
class ValidateForm
{
public function handle($component, Closure $next)
{
if (strlen($component->name) < 3) {
$component->addError('name', 'Имя слишком короткое');
return;
}
if (! filter_var($component->email, FILTER_VALIDATE_EMAIL)) {
$component->addError('email', 'Неверный email');
return;
}
return $next($component);
}
}
Если мы не вызываем $next(), Pipeline останавливается.
Шаг 2. Подготовка данных
namespace App\Pipelines;
use Closure;
class NormalizeEmail
{
public function handle($component, Closure $next)
{
$component->email = strtolower($component->email);
return $next($component);
}
}
Здесь всё просто — изменили данные и передали дальше.
Шаг 3. Сохранение пользователя
namespace App\Pipelines;
use App\Models\User;
use Closure;
class CreateUser
{
public function handle($component, Closure $next)
{
User::create([
'name' => $component->name,
'email' => $component->email,
]);
return $next($component);
}
}
Что мы получили в итоге
Было:
- куча
ifв компоненте - сложно читать
- невозможно переиспользовать
Стало:
- каждый шаг — отдельный класс
- чистый Livewire-компонент
- легко добавлять новые шаги
- код читается как сценарий
->through([
ValidateForm::class,
NormalizeEmail::class,
CreateUser::class,
])
Читается почти как текст:
проверь → подготовь → сохрани
Почему Pipeline — это удобно для новичков
- не нужно знать паттерны
- обычные классы
- обычные методы
- легко дебажить
- легко удалять и добавлять шаги
Когда Pipeline точно стоит использовать
✅ Подходит:
- формы (Livewire)
- обработка данных
- пошаговая бизнес-логика
- фильтрация запросов
- Service Layer
❌ Не стоит использовать:
- для пары
if - если логика очень простая
- если шаги жёстко зависят друг от друга
Частая ошибка новичков
❌ Делать Pipeline «ради Pipeline»
Pipeline — это не магия, а инструмент.
Если код стал проще и понятнее — ты всё сделал правильно.
Итог
Pipeline в Laravel — это способ писать понятный код.
Особенно в связке с Livewire, где:
- компоненты должны быть простыми
- бизнес-логика не должна жить в
render()иsave()