Courses

[FREE] Laravel 12 For Beginners: Your First Project

Form Validation and Error Messages

Summary of this lesson:
- Add backend validation to prevent invalid form submissions
- Use `validate()` in the Controller to enforce rules
- Display validation errors in Blade views
- Use Form Requests to simplify Controller logic

Let's work on validating the form.

Currently, we don't have any validation. If you don't fill out the Create Post form, you will receive an error from the database.


You could add required in the HTML form, and it would work. But this value can be easily removed using the browser developer tool, or the user could send the request not directly from the browser.

It could also be a mobile application with an API or someone maliciously trying to launch the request. So, we need the backend validation.

There are a few ways how to add backend validation. First, each field must have a set of validation rules. These rules can be placed in the Controller itself or a separate Form Request class.

First, let's see how we can do it in the Controller.


Validation Rules in Controller

We must validate the Request, so we need to call the validate() method and provide fields with rules in an array.

app/Http/Controllers/PostController.php:

class PostController extends Controller
{
// ...
 
public function store(Request $request)
{
$request->validate([
'title' => ['required'],
'text' => ['required'],
'category_id' => ['required'],
]);
 
Post::create([
'title' => $request->input('title'),
'text' => $request->input('text'),
'category_id' => $request->input('category_id'),
]);
 
return redirect()->route('posts.index');
}
 
// ...
}

Now, you will be redirected back to the form if you try to submit an empty form.

This is the default behavior: Laravel redirects back with error messages in the session if validation fails.


Showing Validation Messages

Let's show those validation errors. To show errors, we will use a snippet from the official documentation.

@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif

The $errors variable is passed automatically to the Views. In the View where we have form, for example, on the create page, we can add this snippet before the form.

resources/views/posts/create.blade.php:

// ...
<div class="p-6 text-gray-900">
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
 
<form method="POST" action="{{ route('posts.store') }}">
// ...

After posting an empty form, we can see validation error messages.

Here's the GitHub commit for this change.


Validation in Form Requests

Next, I would like to show you how to make your Controllers shorter. For that, Laravel has a concept of Form Request class. Form Requests can also be created using an artisan command.

php artisan make:request StorePostRequest

Then, we replace the Request type in the Controllers method. And move all the fields into the StorePostRequest class rules() method.

app/Http/Controllers/PostController.php:

use App\Http\Requests\StorePostRequest;
 
class PostController extends Controller
{
// ...
 
public function store(Request $request)
public function store(StorePostRequest $request)
{
$request->validate([
'title' => ['required'],
'text' => ['required'],
'category_id' => ['required'],
]);
 
Post::create([
'title' => $request->input('title'),
'text' => $request->input('text'),
'category_id' => $request->input('category_id'),
]);
 
return redirect()->route('posts.index');
}
 
// ...
}

Inside the Form Request class, we see this structure:

app/Http/Requests/StorePostRequest.php:

class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return false;
}
 
public function rules(): array
{
return [
//
];
}
}

The authorize() method indicates whether the user is authorized to make the request. It can be set to true but could contain more checks, such as the user's role.

app/Http/Requests/StorePostRequest.php:

use Illuminate\Foundation\Http\FormRequest;
 
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return false;
return true;
}
 
public function rules(): array
{
return [
'title' => ['required'],
'text' => ['required'],
'category_id' => ['required'],
];
}
}

Also, when using Form Request, the returned result is validated data as an array. This array can be used when creating or updating records using the Request's validated() method.

app/Http/Controllers/PostController.php:

class PostController extends Controller
{
// ...
 
public function store(StorePostRequest $request)
{
$request->validate([
'title' => ['required'],
'text' => ['required'],
'category_id' => ['required'],
]);
 
Post::create([
'title' => $request->input('title'),
'text' => $request->input('text'),
'category_id' => $request->input('category_id'),
]);
 
Post::create($request->validated());
 
return redirect()->route('posts.index');
}
 
// ...
}

Now, the create form works the same way, but the Controller is much shorter. Validating data or creating the record is achieved with just two lines in the Controller.

Here's the GitHub commit for this change.


And... that's it for this practical Laravel course for beginners! Well done if you created a similar project while reading this!

In the next and final lesson, I will give advice on what to learn next.

avatar

Hello

Iam learning Laravel and your courses are great. But, our database and all the infrastructure around it, inclusing several websties already exist, so Laravel will need to play nicely alongside them.

We have a users table and a sessions table, but with slight differences in columns. Users log in using a "username & password", stored on the users table rather than using "email".

Iam a little bit stuck in howto adapt Laravel to auth using our table structure and Postgres Crypt method, and wondered if you had a course that covered tweaking it to work against our method?

Thankyou

avatar

Hi,

We don't have a specific course that would cover your exact needs - sorry.

As for how to change email to username - this is done in the app/Http/Requests/Auth/LoginRequest.php file - there's:

        if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {

That you can override.

Hope that helps a little bit!