Module 4: User Interaction

Forms, Validation, and Authentication.

Securing and Populating Your App

Welcome to Module 4! Your application can now display data from a database, but web apps are interactive. Users need to be able to sign up, log in, and submit their own data. This module covers two fundamental pillars of web development: Authentication (managing users) and handling user input through Forms with robust Validation. Luckily, Laravel makes these complex topics incredibly simple and secure to implement.


1Authentication in Minutes with Laravel Breeze

Building a secure login and registration system from scratch is difficult and error-prone. Laravel provides official "starter kits" that give you a complete, secure authentication system with just a few commands. For beginners, Laravel Breeze is the perfect choice. It's a minimal and simple implementation of all of Laravel's authentication features.

Installing Breeze

You can add Breeze to your existing project using Composer. In your terminal, at the root of your project, run:

composer require laravel/breeze --dev

Once it's downloaded, you can install Breeze into your project using an Artisan command. We'll use the simple Blade stack:

php artisan breeze:install blade

This command does a lot of work for you:

  • It creates login, registration, and password reset views.
  • It creates the routes for all these features in `routes/auth.php`.
  • It creates the necessary controllers to handle the logic.

Finally, run your migrations (to create the `users` table if you haven't already) and install the front-end dependencies:

php artisan migrate
npm install && npm run dev

2Handling Forms and Validating Input

Now that users can log in, let's allow them to create their own blog posts. This requires a form and, crucially, a way to validate the data they submit. You should never trust user input. Validation ensures the data meets your requirements before it ever touches your database.

Creating a Form

Let's create a view for our "Create Post" form at `resources/views/posts/create.blade.php`.

@extends('layouts.app') // Assuming you have a layout

@section('content')
    <h1>Create a New Post</h1>

    <form method="POST" action="/posts">
        @csrf // VERY IMPORTANT! CSRF Protection

        <div>
            <label for="title">Title</label>
            <input type="text" name="title" id="title" required>
        </div>

        <div>
            <label for="content">Content</label>
            <textarea name="content" id="content" required></textarea>
        </div>

        <button type="submit">Create Post</button>
    </form>
@endsection

The `@csrf` directive is essential. It generates a hidden token to protect your application from Cross-Site Request Forgery attacks, a common web vulnerability.

Validating the Request

When this form is submitted, the request will be sent to a controller method. Inside that method, we can validate the incoming data using Laravel's incredibly intuitive validator.

In `PostController`, let's create a `store` method:

use Illuminate\Http\Request;

public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|max:255',
        'content' => 'required|min:10',
    ]);

    // If validation passes, the code continues here.
    // If it fails, Laravel automatically redirects back with errors.

    $post = new Post;
    $post->title = $validatedData['title'];
    $post->content = $validatedData['content'];
    $post->save();

    return redirect('/posts'); // Redirect to the posts list
}

The `validate` method accepts an array of rules. Here, `required|max:255` means the title field must exist and cannot be longer than 255 characters. If any rule fails, Laravel automatically sends the user back to the previous page and flashes the validation errors to the session.

Displaying Validation Errors

Back in our `create.blade.php` file, we can easily display these errors next to each field using the `@error` directive.

<label for="title">Title</label>
<input type="text" name="title" id="title" value="{{ old('title') }}">
@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

The `$message` variable is automatically available inside the `@error` block. The `old('title')` helper repopulates the input field with its previous value so the user doesn't have to re-type everything.


3Complete Workflow: Creating a Post

Let's finalize the full process for creating a post.

1. Define the Routes

We need two routes in `routes/web.php`: one to show the form (`GET`) and one to handle the submission (`POST`).

use App\Http\Controllers\PostController;

// Show the form to create a post
Route::get('/posts/create', [PostController::class, 'create']);

// Store the new post in the database
Route::post('/posts', [PostController::class, 'store']);

2. Create the Controller Methods

We already created the `store` method. Now let's add the `create` method to `PostController` to simply return the view.

public function create()
{
    return view('posts.create');
}

3. Protect Your Routes

We don't want just anyone creating posts. Only logged-in users should be able to. Laravel makes this incredibly easy with "middleware". We can protect our new routes by wrapping them in an auth group.

Route::middleware(['auth'])->group(function () {
    Route::get('/posts/create', [PostController::class, 'create']);
    Route::post('/posts', [PostController::class, 'store']);
});

Now, if a guest tries to visit `/posts/create`, Laravel will automatically redirect them to the login page.