DEV Community

Cover image for How to Build a Generic CRUD Controller in Laravel for Multiple Resources
Abdullah Qasim
Abdullah Qasim

Posted on

How to Build a Generic CRUD Controller in Laravel for Multiple Resources

How to Build a Generic CRUD Controller in Laravel for Multiple Resources

Managing multiple CRUD operations in a Laravel application can be overwhelming, especially when handling a growing number of models. In this post, I'll guide you on creating a generic CRUD controller that allows you to handle existing and future CRUD operations in a single controller.

Why Use a Generic Controller?

A generic controller helps:

  • Minimize repetitive code.
  • Make adding new models a breeze.
  • Provide a consistent structure for your application.

Let’s dive into the implementation step by step!


Step 1: Setting Up the Controller

Start by creating a new controller:

php artisan make:controller GenericController
Enter fullscreen mode Exit fullscreen mode

Step 2: Writing the Controller Logic

Here’s how you can design your GenericController to handle CRUD operations for any model:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Str;

class GenericController extends Controller
{
    protected function getModel($modelName)
    {
        $modelClass = 'App\\Models\\' . Str::studly($modelName);

        if (!class_exists($modelClass)) {
            abort(404, "Model $modelName not found.");
        }

        return new $modelClass;
    }

    public function index($model)
    {
        $modelInstance = $this->getModel($model);
        return response()->json($modelInstance::all());
    }

    public function show($model, $id)
    {
        $modelInstance = $this->getModel($model);
        return response()->json($modelInstance::findOrFail($id));
    }

    public function store(Request $request, $model)
    {
        $modelInstance = $this->getModel($model);
        $data = $request->validate($modelInstance->getFillable());
        $created = $modelInstance::create($data);

        return response()->json($created, 201);
    }

    public function update(Request $request, $model, $id)
    {
        $modelInstance = $this->getModel($model);
        $item = $modelInstance::findOrFail($id);
        $data = $request->validate($modelInstance->getFillable());
        $item->update($data);

        return response()->json($item);
    }

    public function destroy($model, $id)
    {
        $modelInstance = $this->getModel($model);
        $item = $modelInstance::findOrFail($id);
        $item->delete();

        return response()->json(['message' => 'Deleted successfully.']);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Dynamic Routing

Configure your routes to use dynamic endpoints:

use App\Http\Controllers\GenericController;

Route::controller(GenericController::class)->prefix('api/{model}')->group(function () {
    Route::get('/', 'index'); 
    Route::get('/{id}', 'show'); 
    Route::post('/', 'store'); 
    Route::put('/{id}', 'update'); 
    Route::delete('/{id}', 'destroy'); 
});
Enter fullscreen mode Exit fullscreen mode

Step 4: Prepare Your Models

Ensure each model has:

  • A $fillable property to specify mass-assignable fields.

Example for a Post model:

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content'];
}

Enter fullscreen mode Exit fullscreen mode

Key Advantages

  • Scalability: Easily handle new models by adding only the model file.
  • Code Reusability: Reduces redundancy.
  • Simplifies Maintenance: Focus on business logic without worrying about boilerplate code.

When to Use This Approach?

This is ideal for:

  • Applications with standard CRUD logic.
  • Projects where models share common behavior.

For more complex business logic, you may still need dedicated controllers.

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay