Creating the Simplest CRUD Application in Laravel – Part 2

Welcome to Part 2 of our tutorial on creating the simplest CRUD (Create, Read, Update, Delete) application using Laravel. In this part, we’ll enhance our application by adding form validation, improving the user interface with some basic styling, and handling errors gracefully.

Step 7: Adding Form Validation

Laravel makes it easy to validate incoming data. We have already added basic validation in our ItemController. Let’s refine it a bit.

Updating Validation Rules

Open the ItemController and update the store and update methods to include more detailed validation rules:

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

    Item::create($request->all());

    return redirect()->route('items.index')
        ->with('success', 'Item created successfully.');
}

public function update(Request $request, Item $item)
{
    $request->validate([
        'name' => 'required|string|max:255',
        'description' => 'required|string',
    ]);

    $item->update($request->all());

    return redirect()->route('items.index')
        ->with('success', 'Item updated successfully.');
}

Displaying Validation Errors

Next, we need to display validation errors in our forms. Update the create.blade.php and edit.blade.php files to include error messages:

create.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Add New Item</h1>
    <form action="{{ route('items.store') }}" method="POST">
        @csrf
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" name="name" class="form-control" required>
            @error('name')
                <div class="alert alert-danger">{{ $message }}</div>
            @enderror
        </div>
        <div class="form-group">
            <label for="description">Description</label>
            <textarea name="description" class="form-control" required></textarea>
            @error('description')
                <div class="alert alert-danger">{{ $message }}</div>
            @enderror
        </div>
        <button type="submit" class="btn btn-primary">Save</button>
    </form>
</div>
@endsection

edit.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Edit Item</h1>
    <form action="{{ route('items.update', $item->id) }}" method="POST">
        @csrf
        @method('PUT')
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" name="name" class="form-control" value="{{ $item->name }}" required>
            @error('name')
                <div class="alert alert-danger">{{ $message }}</div>
            @enderror
        </div>
        <div class="form-group">
            <label for="description">Description</label>
            <textarea name="description" class="form-control" required>{{ $item->description }}</textarea>
            @error('description')
                <div class="alert alert-danger">{{ $message }}</div>
            @enderror
        </div>
        <button type="submit" class="btn btn-primary">Update</button>
    </form>
</div>
@endsection

Step 8: Improving the User Interface

To make our application look better, we’ll add some basic styling using Bootstrap, a popular CSS framework. Laravel includes Bootstrap out of the box, so we can start using it right away.

See also  Building RESTful APIs with Laravel: A Comprehensive Guide

Adding Bootstrap to the Layout

Open the resources/views/layouts/app.blade.php file and make sure it includes Bootstrap:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple CRUD</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="#">Simple CRUD</a>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
                <li class="nav-item">
                    <a class="nav-link" href="{{ route('items.index') }}">Home</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{{ route('items.create') }}">Add Item</a>
                </li>
            </ul>
        </div>
    </nav>
    <div class="container mt-5">
        @yield('content')
    </div>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Enhancing the Item Views

Now let’s make some improvements to our item views:

index.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Items</h1>
    <a href="{{ route('items.create') }}" class="btn btn-primary mb-3">Add Item</a>
    @if ($message = Session::get('success'))
        <div class="alert alert-success">
            {{ $message }}
        </div>
    @endif
    <table class="table table-bordered">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Description</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($items as $item)
                <tr>
                    <td>{{ $item->id }}</td>
                    <td>{{ $item->name }}</td>
                    <td>{{ $item->description }}</td>
                    <td>
                        <a href="{{ route('items.show', $item->id) }}" class="btn btn-info">View</a>
                        <a href="{{ route('items.edit', $item->id) }}" class="btn btn-warning">Edit</a>
                        <form action="{{ route('items.destroy', $item->id) }}" method="POST" style="display:inline;">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-danger">Delete</button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>
</div>
@endsection

show.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Item Details</h1>
    <table class="table table-bordered">
        <tr>
            <th>ID</th>
            <td>{{ $item->id }}</td>
        </tr>
        <tr>
            <th>Name</th>
            <td>{{ $item->name }}</td>
        </tr>
        <tr>
            <th>Description</th>
            <td>{{ $item->description }}</td>
        </tr>
    </table>
    <a href="{{ route('items.index') }}" class="btn btn-primary">Back to List</a>
</div>
@endsection

Step 9: Handling Errors Gracefully

To handle errors gracefully, we need to customize the error pages. Laravel provides default error pages located in the resources/views/errors directory. We can customize these pages to match the style of our application.

Customizing the 404 Error Page

Create a new file named 404.blade.php in the resources/views/errors directory and add the following content:

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Page Not Found</h1>
    <p>Sorry, the page you are looking for could not be found.</p>
    <a href="{{ route('items.index') }}" class="btn btn-primary">Back to Home</a>
</div>
@endsection

Customizing the 500 Error Page

Create a new file named 500.blade.php in the resources/views/errors directory and add the following content:

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Server Error</h1>
    <p>Sorry, something went wrong on our end. Please try again later.</p>
    <a href="{{ route('items.index') }}" class="btn btn-primary">Back to Home</a>
</div>
@endsection

Conclusion

In this second part of the tutorial, we’ve enhanced our CRUD application by adding form validation, improving the user interface with Bootstrap, and handling errors gracefully with custom error pages. Your application should now be more user-friendly and robust.

See also  IntelliPHP: AI-Powered Code Completion for Your PHP Projects

Stay tuned for Part 3, where we’ll dive deeper into more advanced features and enhancements for our CRUD application!

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.