My Journey Through Laravel Validation: Controllers, Form Requests, and Service Classes

When I first started working with Laravel, validation confused me more than I’d like to admit.

Some tutorials put the rules directly inside the controller, others used these mysterious Form Request classes, and in bigger projects I saw something called service classes. At the time, it felt overwhelming — why were there so many ways to do the same thing?

Over the years, I’ve worked with all three approaches. Each has its pros and cons, and knowing when to use which one can save you a lot of headaches. Here’s how I think about them today.


1. Validation in Controllers

This is where I began — and probably where most Laravel developers do. You can validate inline, right inside your controller method:

public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
        'email' => 'required|email',
    ]);

    // continue with save logic...
}

At first, this felt natural. Everything was in one place, and it worked.

But as soon as the app grew, things got messy. Controllers became bloated — handling validation, business logic, and database calls all together.

My takeaway: controller validation is fine for quick prototypes or very small apps, but it doesn’t scale well.


2. Form Requests

Then I discovered Form Request classes, and it honestly changed the way I write Laravel code. Instead of stuffing validation into the controller, I could move it into a dedicated request class:

class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'email' => 'required|email',
        ];
    }
}

And my controller suddenly looked clean:

public function store(StorePostRequest $request)
{
    // validation already passed!
}

This approach gave me:

  • Cleaner controllers.
  • Centralized and reusable rules.
  • Easy unit testing for validation.
  • Bonus: built-in authorization checks.

My takeaway: Form Requests are the sweet spot for most apps — they’re Laravel’s recommended best practice, and for good reason.


3. Service Classes (Briefly)

Later, on bigger projects, I encountered Service Classes.

A service class is simply a class dedicated to handling a chunk of business logic. Some teams also move validation into these classes, so everything related to a process lives in one place:

class PostService
{
    public function validate(array $data): array
    {
        return Validator::make($data, [
            'title' => 'required|string|max:255',
            'email' => 'required|email',
        ])->validate();
    }
}

And then the controller calls the service:

public function store(Request $request, PostService $service)
{
    $validated = $service->validate($request->all());
    // save logic...
}

This makes sense in large, layered apps where you want controllers thin, and services to own the process logic.

My takeaway: service classes are powerful, but they’re usually only worth the extra structure in bigger, enterprise-style apps.


Wrapping Up

Looking back at my journey:

  • I started with controller validation because it was simple.
  • I moved to Form Requests when I wanted cleaner, testable code.
  • I experimented with Service Classes in larger apps that needed more structure.

Today, I reach for Form Requests by default. They strike the right balance between simplicity and best practice in Laravel apps. And if your app grows into something bigger, you can always refactor toward service classes later.

If you’re just starting out, don’t overthink it. Start with what works, learn the trade-offs, and evolve your approach as your project grows.

In a future article, I’ll dive deeper into Service Classes — what they are, when to use them, and how they can make large apps easier to manage.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top