0

Dependency injection in controllers — automatic resolution

Intermediate5 min read·lv-08-004

Concept

Resource controllers provide a standardized approach to CRUD operations following RESTful conventions. Route::resource() generates 7 routes that map to 7 controller methods.

The 7 resource routes:

VerbURIActionRoute Name
GET/photosindexphotos.index
GET/photos/createcreatephotos.create
POST/photosstorephotos.store
GET/photos/showphotos.show
GET/photos//editeditphotos.edit
PUT/PATCH/photos/updatephotos.update
DELETE/photos/destroyphotos.destroy

API resource controllers: Route::apiResource() generates the same routes minus create and edit (no HTML forms in APIs). Use this for API-only controllers.

Partial resource routes: ->only(['index', 'show']) or ->except(['create', 'edit']) restrict which routes are generated.

Nested resources: Route::resource('posts.comments', PostCommentController::class) generates routes like /posts/{post}/comments/{comment}. The controller receives both parent and child model IDs.

Shallow nesting: ->shallow() avoids deeply nested URLs — only index/store use the parent; show/update/destroy use the child directly.

php artisan make:controller UserController --resource: Generates a controller stub with all 7 method signatures. php artisan make:controller UserController --api: Generates an API resource stub (5 methods, no create/edit). php artisan make:controller UserController --model=User: Generates with type-hinted User parameters.

Code Example

php
<?php
// routes/api.php
use App\Http\Controllers\Api;

Route::apiResource('users', Api\UserController::class);
Route::apiResource('posts', Api\PostController::class);

// Nested resource — post comments
Route::apiResource('posts.comments', Api\PostCommentController::class)->shallow();

// Partial resource — only list and show
Route::apiResource('categories', Api\CategoryController::class)->only(['index', 'show']);

// API Resource Controller
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use App\Http\Resources\UserCollection;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserController extends Controller
{
    public function index(Request $request): UserCollection
    {
        $users = User::with('profile')
            ->when($request->search, fn($q, $s) => $q->where('name', 'like', "%$s%"))
            ->paginate(15);
        return new UserCollection($users);
    }

    public function show(User $user): UserResource
    {
        return new UserResource($user->load('profile', 'orders'));
    }

    public function store(Request $request): UserResource
    {
        $validated = $request->validate([
            'name'     => 'required|string|max:255',
            'email'    => 'required|email|unique:users',
            'password' => 'required|string|min:8',
        ]);
        $user = User::create([...$validated, 'password' => bcrypt($validated['password'])]);
        return new UserResource($user);
    }

    public function update(Request $request, User $user): UserResource
    {
        $user->update($request->validated());
        return new UserResource($user);
    }

    public function destroy(User $user): \Illuminate\Http\Response
    {
        $user->delete();
        return response()->noContent(); // 204 No Content
    }
}