| name | laravel-enterprise |
| description | Builds Laravel APIs and applications following enterprise patterns: Repository pattern with interfaces, Service Layer for business logic, API Resources for response transformation, Form Requests for validation, and structured exception handling. Use when creating Laravel APIs, designing service layers, refactoring fat controllers, implementing repository pattern, working with Eloquent in a team context, or asked about Laravel architecture for projects with more than one developer.
|
| license | MIT |
| metadata | {"author":"iamBrzDev","version":"1.0"} |
When to activate
- Creating a new Laravel API or module
- "How do I structure this in Laravel?"
- Refactoring a fat controller
- Designing or implementing the service layer
- Implementing Repository pattern in Laravel
- Any mention of Laravel architecture, Eloquent best practices, or team-scale structure
Project Structure
app/
├── Http/
│ ├── Controllers/Api/V1/ # Thin controllers only
│ ├── Requests/Order/ # All validation lives here
│ └── Resources/ # All response shaping lives here
├── Services/ # All business logic lives here
├── Repositories/
│ ├── Contracts/ # Interfaces
│ └── Eloquent/ # Implementations
├── DTOs/
└── Exceptions/
The Layering Rule
Request → FormRequest → Controller → Service → Repository → Eloquent
Never skip layers. Never call Eloquent directly from a Controller.
Controllers — Always thin
class OrderController extends Controller
{
public function __construct(private OrderService $service) {}
public function store(CreateOrderRequest $request): JsonResponse
{
$order = $this->service->create($request->toDTO());
return response()->json(new OrderResource($order), 201);
}
}
class OrderController extends Controller
{
public function store(Request $request): JsonResponse
{
$request->validate([...]);
$order = Order::create($request->all());
return response()->json($order);
}
}
Form Requests — All validation here
class CreateOrderRequest extends FormRequest
{
public function rules(): array
{
return [
'customer_id' => ['required', 'integer', 'exists:customers,id'],
'items' => ['required', 'array', 'min:1'],
'items.*.product_id' => ['required', 'integer', 'exists:products,id'],
'items.*.quantity' => ['required', 'integer', 'min:1'],
];
}
public function toDTO(): CreateOrderDTO
{
return new CreateOrderDTO(
customerId: $this->integer('customer_id'),
items: $this->collect('items')->toArray(),
);
}
}
Repository Pattern
interface OrderRepositoryInterface
{
public function findByIdOrFail(int $id): Order;
public function create(CreateOrderDTO $dto): Order;
}
class OrderRepository implements OrderRepositoryInterface
{
public function findByIdOrFail(int $id): Order
{
return Order::with(['items', 'customer'])->findOrFail($id);
}
public function create(CreateOrderDTO $dto): Order
{
return DB::transaction(function () use ($dto) {
$order = Order::create(['customer_id' => $dto->customerId]);
$order->items()->createMany($dto->items);
return $order->load('items');
});
}
}
$this->app->bind(OrderRepositoryInterface::class, OrderRepository::class);
API Resources — Always transform
return new OrderResource($order);
return OrderResource::collection($orders);
return response()->json($order);
Non-negotiables
- Form Requests for all validation
- API Resources for all responses
- DTOs between layers — never pass
$request to services
- No business logic in models
- Explicit
with() loading — never lazy load in loops
Reference files
references/service-layer.md — Transactions, domain events, queued jobs