Ещё вчера я безбожно плодил повторяющийся код в контроллерах laravel из-за того что в приложении может в нескольких точках выполняться одно и тоже действие, например — это создание пользователя.
Это происходит в админ панели в форме создания пользователя, в API контроллере и может быть даже в artisan команде.
class UserController
{
public function create(CreateUserRequest $request)
{
$user = new User;
$user->email = $request->email;
$user->password = bcrypt($request->password);
$user->save();
return redirect('users/' . $user->id);
}
}
class UserApiController
{
public function create(CreateUserRequest $request)
{
$user = new User;
$user->email = $request->email;
$user->password = bcrypt($request->password);
$user->save();
return new UserResponse($user);
}
}
Легко заметить классы выше отличаются лишь на одну строку.
Недавно я обнаружил элегантное решение этой проблемы, прочитав статью на medium.
Повторение удаляется добавлением нового класса:
class UserCreateAction
{
public function execute(CreateUserRequest $request): User
{
$user = new User;
$user->email = $request->email;
$user->password = bcrypt($request->password);
$user->save();
return $user;
}
}
class UserController
{
public function create(CreateUserRequest $request, CreateUserAction $action)
{
return redirect('users/' . $action->execute($request)->id);
}
}
class UserApiController
{
public function create(CreateUserRequest $request)
{
return new UserResponse($action->execute($request));
}
}
Это же так очевидно! И как я сам до этого не додумался? Наверное я не один такой.
Я пошёл ещё дальше и создал целый пакет для laravel, в котором есть всего одна команда make:auth
.
php artisan make:action Users/CreateUserAction
Она создаст следующий код:
<?php
namespace App\Actions\Users;
use App\User;
use Slexx\Actions\Action;
class CreateUserAction extends Action
{
/**
* @param array $data
* @return User
*/
public function execute(array $data)
{
$user = User::create($data);
return $user;
}
}
Если вдруг кому то интересно, установка через composer:
composer require slexx/laravel-actions
После обновления composer, добавьте поставщика услуг в массив providers в файл config/app.php
.
Slexx\Actions\ActionsServiceProvider::class,