Lesson 14 of 50 – Forms and CSRF Protection
28%

Laravel Forms and CSRF Protection

Forms allow users to submit information such as student names, email addresses, admission details, and contact messages. Laravel provides request handling, CSRF protection, and validation tools to process form data safely.

1. Create a Simple Laravel Form

First, create a Blade view named resources/views/contact.blade.php.

<!DOCTYPE html>
<html>
<head>
    <title>Contact Form</title>
</head>
<body>

    <h1>Contact Us</h1>

    <form action="/contact" method="POST">
        <label>Name:</label>
        <input type="text" name="name" required>

        <br><br>

        <label>Email:</label>
        <input type="email" name="email" required>

        <br><br>

        <button type="submit">Submit</button>
    </form>

</body>
</html>

This form sends the name and email fields to the /contact URL using the POST method.

In Laravel, a POST form must include a CSRF token. We will add it in the next section.

2. Protect Forms Using @csrf

Laravel protects web routes against Cross-Site Request Forgery (CSRF) attacks. Add the @csrf directive inside forms that submit requests to protected web routes.

<form action="/contact" method="POST">

    @csrf

    <label>Name:</label>
    <input type="text" name="name" required>

    <label>Email:</label>
    <input type="email" name="email" required>

    <button type="submit">Submit</button>

</form>

Laravel generates a hidden input containing the CSRF token.

Without a valid token, a POST request to a route protected by Laravel's web middleware will normally be rejected.

Never remove CSRF protection simply to make a form work. Check that the form includes @csrf and submits to the correct route.
3. Receive Form Data in a Route

Laravel's Request object provides access to submitted form values.

In routes/web.php:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('/contact', function () {
    return view('contact');
});

Route::post('/contact', function (Request $request) {
    $name = $request->input('name');
    $email = $request->input('email');

    return 'Name: ' . $name . ', Email: ' . $email;
});

The GET route displays the form, while the POST route processes the submitted values.

For production applications, validate submitted values before processing them. For larger features, move the processing logic into a controller.

4. Create a Form Using a Controller

Controllers help organize form-related logic. Create a controller using Artisan:

php artisan make:controller ContactController

Open app/Http/Controllers/ContactController.php and add these methods inside the class:

public function create()
{
    return view('contact');
}

public function store(\Illuminate\Http\Request $request)
{
    $name = $request->input('name');

    return 'Welcome, ' . $name;
}

Register the routes in routes/web.php:

use App\Http\Controllers\ContactController;

Route::get('/contact', [ContactController::class, 'create']);

Route::post('/contact', [ContactController::class, 'store']);

The create() method displays the form, and store() handles the submission.

The submitted data should be validated before it is saved or otherwise used.

5. Validate Form Data

Validation checks whether submitted data meets your application's requirements.

Inside ContactController.php:

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

    return 'Form submitted successfully!';
}

These rules require a name and a valid email address. The name is limited to 100 characters.

If validation fails, Laravel automatically redirects back with validation errors for a typical browser form request.

The $validated array contains the validated fields and can be used for subsequent processing.

6. Display Validation Errors in Blade

You can display validation errors above the form using Blade directives.

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

To display the error for one field, use @error.

<input
    type="text"
    name="name"
    value="{{ old('name') }}"
>

@error('name')
    <div class="text-danger">{{ $message }}</div>
@enderror

The old('name') helper repopulates the previous input value after a validation redirect.

Use escaped Blade output for error messages and user-provided values.

7. Use Different Form Input Types

HTML forms support several input types for collecting different kinds of information.

<form action="/student" method="POST">
    @csrf

    <label>Student Name:</label>
    <input type="text" name="name" required>

    <label>Email:</label>
    <input type="email" name="email" required>

    <label>Age:</label>
    <input type="number" name="age" min="1" max="100">

    <label>Course:</label>
    <select name="course">
        <option value="PHP">PHP</option>
        <option value="Laravel">Laravel</option>
        <option value="React">React</option>
    </select>

    <label>Gender:</label>
    <input type="radio" name="gender" value="Male"> Male
    <input type="radio" name="gender" value="Female"> Female

    <button type="submit">Register</button>
</form>

The browser provides basic input controls, but server-side validation is still necessary because browser-side checks can be bypassed.

8. Redirect After Successful Submission

After processing a form, you can redirect the user to another page and display a one-time success message.

Inside a controller:

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

    // Process or save the validated data here.

    return redirect()
        ->route('contact.create')
        ->with('success', 'Form submitted successfully!');
}

Register a named GET route:

Route::get('/contact', [ContactController::class, 'create'])
    ->name('contact.create');

Display the success message in Blade:

@if (session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif

A redirect after a successful POST helps prevent accidental duplicate submissions when users refresh the resulting page.

9. Practical Assignment

Create a student admission form using Laravel.

  1. Create a Blade view named admission.blade.php.
  2. Add fields for student name, email, age, and course.
  3. Include @csrf inside the form.
  4. Create GET and POST routes for the form.
  5. Create an AdmissionController to process submissions.
  6. Validate the name, email, age, and course fields.
  7. Display validation errors beside the relevant fields.
  8. Show a success message after processing valid data.
  9. Test the form with both valid and invalid inputs.

Remember: never trust submitted form data simply because the browser marks a field as required. Always validate important data on the server.


🧠 Quick Quiz

1. Which Blade directive adds a CSRF token to a form?




2. Which method validates submitted request data?




3. Which helper retrieves an old input value?