A clean, scalable architecture for organizing business logic in PHP applications using Action and Service patterns.
This repository demonstrates a structured approach to building maintainable PHP applications by separating business logic into Actions (complete operations) and Services (reusable logic).
It’s all about maintainability. Actions keep your code focused on single, complete tasks. Services handle the repetitive, lower-level work. This separation makes your application easier to test, debug, and extend. You want less clutter, more clarity.
Read the full guidelines — includes examples, naming conventions, and best practices. Dive in for the specifics.
// Creates a complete order with validation, payment, notifications
OrderCreateAction
// Adds item to cart with all side effects
CartItemAddAction
// Processes search with filtering and sorting
SearchAction
// Validates cart items (used by multiple actions)
CartItemValidator
// Figures out when stuff gets delivered
DeliveryScheduleService
// Handles external API calls
TehnomirApi
app/
├── Actions/ # Complete business operations
│ ├── Cart/
│ ├── Order/
│ └── Search/
├── Services/ # Reusable business logic
│ ├── Cart/
│ ├── Order/
│ └── External/
└── ...
Requirement | Where it goes | Example |
---|---|---|
Initiate a user-driven workflow | Action | OrderCreateAction |
Logic or math you use everywhere | Service | DeliveryScheduleService |
Execute a complete business process | Action | CartCheckoutAction |
Data validation or transformation | Service | CartItemValidator |
Use Actions when orchestrating workflows or business processes initiated by user requests. Services are best for logic, validation, or calculations that need to be reused across multiple features. This separation improves maintainability and clarity in project organization.
- ✅
OrderCreateAction
- ✅
CartItemAddAction
- ❌
CreateOrderAction
(Nope, not like this. Don’t flip it.)
- ✅
DeliveryScheduleService
- ✅
CartItemValidator
- ❌
DataService
(What even is this? Be specific.)
- Actions: Responsible for orchestrating workflows and managing side effects.
- Services: Encapsulate pure, reusable business logic—no side effects.
- Single Responsibility: Each class is designed for one clear purpose.
- Dependency Injection: Employ constructor injection for maintainability.
- Type Safety: Explicitly declare types and return values.
- Actions: Hit them with integration tests. Make sure the full workflow doesn’t explode.
- Services: Hit with unit tests. Laser focus on the pure logic, nothing else.
public function store(OrderStoreRequest $request, OrderCreateAction $action): OrderResource
{
$dto = new OrderCreateDTO(...$request->validated());
$order = $action->handle($dto, auth()->id());
return OrderResource::make($order);
}
- Full Guidelines - Complete guide
- Laravel Actions and Services - Article