Name: Actions
Description: Single-purpose business logic classes that encapsulate one well-defined business operation. Actions are the primary location for business logic in Laravel applications, invoked from controllers, commands, or jobs.
Compatible Agents: general-purpose, backend
Tags: app/Actions/**/*.php, laravel, php, backend, business-logic, action
Rules
- Action classes live in
app/Actions/
- Each action represents one single business operation — if you can't describe it in a single sentence, split it up
- Use a clear verb-noun naming pattern:
CreateInvoice, SendPasswordResetEmail, ArchiveExpiredSubscriptions
- Never use vague names like
InvoiceAction or UserHandler
- Actions expose a single public
execute() method
- Keep the constructor for dependency injection only
- Actions are resolved via the service container
- Never include HTTP concerns (request, response, redirects) in an action
- Never put multi-domain orchestration in an action — use a Service instead
- Never put reusable formatting or utility logic in an action — use a Helper
Examples
namespace App\Actions;
use App\Models\Invoice;
use App\Models\Order;
use App\Notifications\InvoiceCreatedNotification;
class CreateInvoice
{
public function __construct(
private readonly GenerateInvoicePdf $generatePdf,
) {}
public function execute(Order $order): Invoice
{
$invoice = Invoice::create([
'order_id' => $order->id,
'amount' => $order->total,
'due_date' => now()->addDays(30),
]);
$this->generatePdf->execute($invoice);
$order->user->notify(new InvoiceCreatedNotification($invoice));
return $invoice;
}
}
// Controller usage
class InvoiceController extends Controller
{
public function store(StoreInvoiceRequest $request, CreateInvoice $action): JsonResponse
{
$order = Order::findOrFail($request->validated('order_id'));
$invoice = $action->execute($order);
return new JsonResponse(new InvoiceResource($invoice), 201);
}
}
// Command usage
class GenerateInvoicesCommand extends Command
{
public function handle(CreateInvoice $action): int
{
Order::pending()->each(fn ($order) => $action->execute($order));
return self::SUCCESS;
}
}
Anti-Patterns
- Putting HTTP concerns (
Request, Response, redirects) inside an action
- Creating multi-step orchestration across domains in a single action (use a Service)
- Naming an action vaguely:
InvoiceAction, UserHandler, DataProcessor
- Adding multiple
execute() methods or public methods beyond the single operation
- Adding business logic in a constructor — use
execute() for that
- Performing database queries unrelated to the action's single responsibility
References
- Laravel Service Container
- Related:
Services/SKILL.md — for multi-domain orchestration
- Related:
Jobs/SKILL.md — for deferring actions to the queue
- Related:
Controllers/SKILL.md — for how controllers delegate to actions
1---2name: actions-43description: Single-purpose business logic classes that encapsulate one well-defined business operation. Actions are the primary location for business logic in Laravel applications, invoked from controllers, commands, or jobs.4---5
6**Name:** Actions
7**Description:** Single-purpose business logic classes that encapsulate one well-defined business operation. Actions are the primary location for business logic in Laravel applications, invoked from controllers, commands, or jobs.
8**Compatible Agents:** general-purpose, backend
9**Tags:** app/Actions/**/*.php, laravel, php, backend, business-logic, action
10
11## Rules
12
13- Action classes live in `app/Actions/`
14- Each action represents **one single business operation** — if you can't describe it in a single sentence, split it up
15- Use a clear verb-noun naming pattern: `CreateInvoice`, `SendPasswordResetEmail`, `ArchiveExpiredSubscriptions`
16- Never use vague names like `InvoiceAction` or `UserHandler`
17- Actions expose a single public `execute()` method
18- Keep the constructor for dependency injection only
19- Actions are resolved via the service container
20- Never include HTTP concerns (request, response, redirects) in an action
21- Never put multi-domain orchestration in an action — use a Service instead
22- Never put reusable formatting or utility logic in an action — use a Helper
23
24## Examples
25
26```php
27namespace App\Actions;
28
29use App\Models\Invoice;
30use App\Models\Order;
31use App\Notifications\InvoiceCreatedNotification;
32
33class CreateInvoice
34{
35 public function __construct(
36 private readonly GenerateInvoicePdf $generatePdf,
37 ) {}
38
39 public function execute(Order $order): Invoice
40 {
41 $invoice = Invoice::create([
42 'order_id' => $order->id,
43 'amount' => $order->total,
44 'due_date' => now()->addDays(30),
45 ]);
46
47 $this->generatePdf->execute($invoice);
48
49 $order->user->notify(new InvoiceCreatedNotification($invoice));
50
51 return $invoice;
52 }
53}
54```
55
56```php
57// Controller usage
58class InvoiceController extends Controller
59{
60 public function store(StoreInvoiceRequest $request, CreateInvoice $action): JsonResponse
61 {
62 $order = Order::findOrFail($request->validated('order_id'));
63 $invoice = $action->execute($order);
64
65 return new JsonResponse(new InvoiceResource($invoice), 201);
66 }
67}
68
69// Command usage
70class GenerateInvoicesCommand extends Command
71{
72 public function handle(CreateInvoice $action): int
73 {
74 Order::pending()->each(fn ($order) => $action->execute($order));
75
76 return self::SUCCESS;
77 }
78}
79```
80
81## Anti-Patterns
82
83- Putting HTTP concerns (`Request`, `Response`, redirects) inside an action
84- Creating multi-step orchestration across domains in a single action (use a Service)
85- Naming an action vaguely: `InvoiceAction`, `UserHandler`, `DataProcessor`
86- Adding multiple `execute()` methods or public methods beyond the single operation
87- Adding business logic in a constructor — use `execute()` for that
88- Performing database queries unrelated to the action's single responsibility
89
90## References
91
92- [Laravel Service Container](https://laravel.com/docs/container)
93- Related: `Services/SKILL.md` — for multi-domain orchestration
94- Related: `Jobs/SKILL.md` — for deferring actions to the queue
95- Related: `Controllers/SKILL.md` — for how controllers delegate to actions