Co je vzor akce v systému Laravel?
Vzor Action je jednoduchý architektonický vzor používaný v Laravelu a dalších aplikacích PHP k zapouzdření jedné logické jednotky uvnitř vyhrazené třídy. Typicky má třída action:
- Jediná veřejná metoda s nejčastějším názvem
handle()který obsahuje základní logiku. - Konstruktor, který vloží všechny požadované závislosti (např. jiné akce, služby, úložiště).
Tento vzor podporuje čistší, opakovaně použitelný a lépe testovatelný kód. Akční třídy jsou obvykle umístěny pod app/Actions a slouží k udržování štíhlých a soustředěných řadičů, příkazů a úloh.
namespace App\Actions; use App\Models\User; class CreateUser{ public function handle(array $data): User { return User::create($data); }}
Výhody akčního vzoru
1. Zapište jednou, volejte kdekoli (kontextově nezávislé)
Akci lze zavolat z libovolného kontextu: kontrolérů, úloh, konzolových příkazů, testů, posluchačů událostí atd.
// In a controllerclass UserController extends Controller{ public function store(Request $request, CreateUser $createUser) { $user = $createUser->handle($request->validated()); return response()->json($user); }}
// In a job/commandpublic function handle(CreateUser $createUser){ $createUser->handle($this->data);}
2. Žádné irelevantní závislostní injekce
Na rozdíl od tříd služeb s mnoha nesouvisejícími metodami jsou třídy akcí zaměřené. Každá třída zpracovává jednu úlohu a dostává pouze ty závislosti, které potřebuje. Výsledkem jsou stručné a účelné konstruktory. Díky tomuto přístupu se vyhnete tomu, aby byl konstruktor naplněn mnoha injektovanými závislostmi, které mohou být použity jen několika metodami.
Na rozdíl od tříd služeb s mnoha nesouvisejícími metodami jsou třídy akcí zaměřené. Každá třída zpracovává jednu úlohu a dostává pouze ty závislosti, které potřebuje. Výsledkem jsou stručné a účelné konstruktory.
3. Snadnější testování v izolaci
Protože akce zapouzdřuje jednu pracovní jednotku, je snazší ji testovat nezávisle na vrstvě HTTP nebo jiných službách.
public function test_it_creates_a_user(){ $action = new CreateUser(); $user = $action->handle([ 'name' => 'Jane Doe', 'email' => 'jane@example.com', 'password' => bcrypt('password'), ]); $this->assertDatabaseHas('users', [ 'email' => 'jane@example.com', ]); $this->assertEquals('Jane Doe', $user->name);}
Osvědčené postupy
1. Struktura: Umístěte akce pod app/Actions
Uspořádejte své akční třídy v app/Actions adresář pro lepší vyhledatelnost.
app/└── Actions/ ├── CreateUser.php ├── UpdateUser.php
2. Úmluva o pojmenování: {Action}{Resource}.php
Používejte jasné a konzistentní pojmenování, např. CreateUser, UpdateProfile, nebo DeletePost.
3. Název metody: Preferovat handle()
Držte se handle() kvůli konzistenci s úlohami a posluchači Laravelu. Alternativy zahrnují __invoke, execute(), nebo run() ale pouze v případě, že váš tým preferuje jiný standard.
public function handle(array $data): User
4. Parametry metody
V závislosti na případu použití předejte buď prostředek a data, nebo pouze data.
// For updating existing resourcepublic function handle(User $user, array $data): User // For creating new resourcepublic function handle(array $data): User
5. Zabalte logiku do DB::transaction()
Pokud vaše akce provádí více operací nebo volá jiné akce, zabalte logiku do transakce, abyste zajistili konzistenci.
public function __construct( public SyncUserRoles $syncUserRoles, public AssignTeam $assignTeam,) {} public function handle(array $data): User{ return DB::transaction(function () use ($data) { $user = User::create($data); // injected actions $this->syncUserRoles->handle($user, $data['roles']); $this->assignTeam->handle($user); return $user; });}
6. Vysílání událostí v případě potřeby
Pokud vaše akce změní prostředek a chcete o tom informovat frontend (např. prostřednictvím Reverbu nebo Inertia), vysílejte události.
use App\Events\UserCreated; broadcast(new UserCreated($user))->toOthers();
7. Vrácení zdroje
Vrátí upravený nebo vytvořený prostředek z vaší akce.
return $user;
8. V případě potřeby provádějte další akce
Třídy akcí mohou být závislé na jiných akcích a vytvářet tak komplexní chování.
public function __construct( protected SyncUserRoles $syncUserRoles, protected AssignTeam $assignTeam,) {}