Laravel 12: CRUD Application Example Tutorial

Hi! Learn Laravel 12 CRUD operations: Create, Read, Update, Delete for efficient database management. Master web app development with Laravel! #Laravel #CRUD #WebDevelopment.

Laravel 12: CRUD Application Example Tutorial Image

Hi there! In this tutorial, I’ll walk you through a step-by-step example of performing CRUD operations in Laravel 12.

What is CRUD?
CRUD stands for Create, Read, Update, and Delete. These are the four essential functions for managing data in any application. Whether you're building a blog, e-commerce site, or any app with a database, CRUD is the backbone of data handling.

What We’ll Build

We’ll create a simple Product Management System using Laravel 12. Here’s what we’ll cover:

  1. Database Setup: Create a products table with name and detail columns using Laravel migrations.
  2. Routes, Controller, and Model: Set up the necessary files to handle product operations.
  3. Views: Design user-friendly interfaces using Bootstrap 5 for a clean and responsive layout.

By the end of this tutorial, you’ll have a fully functional CRUD application in Laravel 12. Let’s dive in and get started!

Steps for Laravel 12 CRUD Operation Example

  • Step 1: Install Laravel 12
  • Step 2: MySQL Database Configuration
  • Step 3: Create Migration
  • Step 4: Create Form Request Validation Class
  • Step 5: Create Controller and Model
  • Step 6: Add Resource Route
  • Step 7: Update AppServiceProvider
  • Step 8: Add Blade Files
  • Step 9: Run Laravel App

Follow these steps to build a fully functional CRUD app in Laravel 12! 🚀

Step 1: Install Laravel 12

First, let’s start by setting up a fresh Laravel 12 application. Since we’re building this project from scratch, open your terminal or command prompt and run the following command to install Laravel 12:

composer create-project laravel/laravel laravel-12-crud

This command will create a new Laravel project named laravel-11-crud. Once the installation is complete, navigate into your project directory:

cd laravel-12-crud

Now, you’re ready to start building your CRUD application in Laravel 12! 🚀

Step 2: MySQL Database Configuration

In Laravel 12, the default database connection uses SQLite. However, if you want to use MySQL, you’ll need to update the .env file with your MySQL database details. Here’s how:

  1. Open the .env file in your Laravel project.
  2. Update the following lines with your MySQL database credentials:

    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=your_database_name
    DB_USERNAME=your_database_username
    DB_PASSWORD=your_database_password

    Replace your_database_name, your_database_username, and your_database_password with your actual MySQL database details.

  3. Save the .env file.

Now, Laravel is configured to connect to your MySQL database! 🎉 Next, we’ll create a migration for the products table.

Step 3: Create Migration

In this step, we’ll create a products table with name and detail columns using Laravel migration. Follow these steps:

  1. Generate Migration File

    Run the following command to create a migration file:

    php artisan make:migration create_products_table --create=products

    This will generate a migration file in the database/migrations directory.

  2. Update Migration File

    Open the newly created migration file and define the products table structure. Add the following code:

    <?php
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    return new class extends Migration
    {
        /**
         * Run the migrations.
         */
        public function up(): void
        {
            Schema::create('products', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->text('detail');
                $table->timestamps();
            });
        }
        /**
         * Reverse the migrations.
         */
        public function down(): void
        {
            Schema::dropIfExists('products');
        }
    };

    Here, we’ve added two columns:

    • name (string) for the product name.
    • detail (text) for the product description.
  3. Run the Migration

    Execute the migration to create the products table in your database:

    php artisan migrate

    This command will create the products table in your MySQL database.

Now, your database is ready to store product data! 🚀 Next, we’ll create a Form Request Validation Class to handle input validation.

Step 4: Create Form Request Validation Class

In this step, we’ll create two form request classes to handle validation for the store() and update() methods in the controller. These classes ensure that the input data is validated before being processed.

  1. Create ProductStoreRequest for Store Operation

    Run the following command to create a request class for storing products:

    php artisan make:request ProductStoreRequest

    Open the generated file at app/Http/Requests/ProductStoreRequest.php and update it with the following code:

    <?php
    namespace App\Http\Requests;
    use Illuminate\Foundation\Http\FormRequest;
    class ProductStoreRequest extends FormRequest
    {
        /**
         * Determine if the user is authorized to make this request.
         */
        public function authorize(): bool
        {
            return true; // Allow all users to make this request
        }
      
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
         */
        public function rules(): array
        {
            return [
                'name' => 'required',   // Name is required
                'detail' => 'required'  // Detail is required
            ];
        }
    }
  2. Create ProductUpdateRequest for Update Operation

    Run the following command to create a request class for updating products:

    php artisan make:request ProductUpdateRequest
    

    Open the generated file at app/Http/Requests/ProductUpdateRequest.php and update it with the following code:

    <?php
    namespace App\Http\Requests;
    use Illuminate\Foundation\Http\FormRequest;
    class ProductUpdateRequest extends FormRequest
    {
        /**
         * Determine if the user is authorized to make this request.
         */
        public function authorize(): bool
        {
            return true; // Allow all users to make this request
        }
      
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
         */
        public function rules(): array
        {
            return [
                'name' => 'required',   // Name is required
                'detail' => 'required' // Detail is required
            ];
        }
    }

What These Classes Do

  • Validation Rules: Both classes ensure that the name and detail fields are required before storing or updating a product.
  • Authorization: The authorize() method returns true, allowing all users to make these requests. You can customize this for role-based access if needed.

Now, these request classes are ready to be used in the controller for validation! 🚀 Next, we’ll create the Controller and Model for the product module.

Step 5: Create Controller and Model

In this step, we’ll create a resource controller (ProductController) and update the Product model to handle CRUD operations for the products table.

  1. Create Resource Controller

    Run the following command to generate a resource controller with a model

    php artisan make:controller ProductController --resource --model=Product

    This command will create a ProductController file at app/Http/Controllers/ProductController.php with seven default methods:

    • index(): Display a list of products.
    • create(): Show the form to create a new product.
    • store(): Save a new product to the database.
    • show(): Display a specific product.
    • edit(): Show the form to edit a product.
    • update(): Update a product in the database.
    • destroy(): Delete a product from the database.

    Now, update the ProductController.php file with the following code:

    <?php
    namespace App\Http\Controllers;
    use App\Models\Product;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\Http\Response;
    use Illuminate\View\View;
    use App\Http\Requests\ProductStoreRequest;
    use App\Http\Requests\ProductUpdateRequest;
    class ProductController extends Controller
    {
        /**
         * Display a listing of the resource.
         */
        public function index(): View
        {
            $products = Product::latest()->paginate(5);
              
            return view('products.index', compact('products'))
                        ->with('i', (request()->input('page', 1) - 1) * 5);
        }
        
        /**
         * Show the form for creating a new resource.
         */
        public function create(): View
        {
            return view('products.create');
        }
        
        /**
         * Store a newly created resource in storage.
         */
        public function store(ProductStoreRequest $request): RedirectResponse
        {   
            Product::create($request->validated());
               
            return redirect()->route('products.index')
                             ->with('success', 'Product created successfully.');
        }
      
        /**
         * Display the specified resource.
         */
        public function show(Product $product): View
        {
            return view('products.show', compact('product'));
        }
      
        /**
         * Show the form for editing the specified resource.
         */
        public function edit(Product $product): View
        {
            return view('products.edit', compact('product'));
        }
      
        /**
         * Update the specified resource in storage.
         */
        public function update(ProductUpdateRequest $request, Product $product): RedirectResponse
        {
            $product->update($request->validated());
              
            return redirect()->route('products.index')
                            ->with('success', 'Product updated successfully');
        }
      
        /**
         * Remove the specified resource from storage.
         */
        public function destroy(Product $product): RedirectResponse
        {
            $product->delete();
               
            return redirect()->route('products.index')
                            ->with('success', 'Product deleted successfully');
        }
    }
  2. Update Product Model

    Open the Product model at app/Models/Product.php and update it with the following code:

    <?php
    namespace App\Models;
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    class Product extends Model
    {
        use HasFactory;
        protected $fillable = [
            'name',
            'detail',
        ];
    }

    The $fillable property specifies which fields can be mass-assigned when creating or updating a product.

What We’ve Done

  • Created a resource controller with methods for handling CRUD operations.
  • Used the ProductStoreRequest and ProductUpdateRequest classes for validation.
  • Updated the Product model to allow mass assignment for name and detail fields.

Now, the backend logic for CRUD operations is ready! 🚀 Next, we’ll define routes for the product module.

Step 6: Add Resource Route

In this step, we’ll define a resource route for the ProductController to handle all CRUD operations. Open the routes/web.php file and add the following code:

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::get('/', function () {
    return view('welcome');
});
// Resource Route for Products
Route::resource('products', ProductController::class);

What This Route Does:

The Route::resource() method automatically generates the routes for CRUD operations

Why Use Resource Routes?

  • Simplifies Routing: Instead of defining individual routes for each CRUD operation, a single line of code handles all routes.
  • Consistency: Follows RESTful conventions, making your application more organized and maintainable.

Now, your application has all the necessary routes to handle product CRUD operations! 🚀 Next, we’ll update the AppServiceProvider to enable Bootstrap pagination styling.

Step 7: Update AppServiceProvider

To use Bootstrap 5 for pagination in your Laravel application, you need to configure it in the AppServiceProvider.php file. Follow the steps below to update your service provider:

Open the file located at: app/Providers/AppServiceProvider.php

Add the following code:

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator;
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // Register additional services here if needed
    }
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        // Enable Bootstrap 5 styling for pagination
        Paginator::useBootstrapFive();
    }
}

Now, Laravel's pagination links will automatically follow Bootstrap 5 styling. No extra CSS or customization is needed! 🎉

Step 8: Add Blade Files

In this step, we’ll set up the Blade templates required for the CRUD application. We’ll first create a layout file, then individual views for listing, creating, editing, and displaying products.

  1. Create a Layout File

    File: resources/views/products/layout.blade.php

    This will serve as the base layout for all product-related views.

    <!DOCTYPE html>
    <html>
    <head>
        <title>Laravel 12 CRUD Application - Tutorial-tools</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
    </head>
    <body>
    <div class="container mt-4">
        @yield('content')
    </div>
    </body>
    </html>
  2. Product Listing Page

    File: resources/views/products/index.blade.php

    This view displays a paginated list of products.

    @extends('products.layout')
    @section('content')
    <div class="card">
      <h2 class="card-header">Laravel 12 CRUD Example - Tutorial-Tools</h2>
      <div class="card-body">
      
            @if(session('success'))
                <div class="alert alert-success">{{ session('success') }}</div>
            @endif
      
            <div class="d-flex justify-content-end">
                <a class="btn btn-success btn-sm" href="{{ route('products.create') }}">
                    <i class="fa fa-plus"></i> Create New Product
                </a>
            </div>
            <table class="table table-bordered table-striped mt-3">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>Name</th>
                        <th>Details</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    @forelse ($products as $product)
                        <tr>
                            <td>{{ $loop->iteration }}</td>
                            <td>{{ $product->name }}</td>
                            <td>{{ $product->detail }}</td>
                            <td>
                                <form action="{{ route('products.destroy', $product->id) }}" method="POST">
                                    <a class="btn btn-info btn-sm" href="{{ route('products.show', $product->id) }}">
                                        <i class="fa-solid fa-list"></i> Show
                                    </a>
                                    <a class="btn btn-primary btn-sm" href="{{ route('products.edit', $product->id) }}">
                                        <i class="fa-solid fa-pen-to-square"></i> Edit
                                    </a>
                                    @csrf
                                    @method('DELETE')
                                    <button type="submit" class="btn btn-danger btn-sm">
                                        <i class="fa-solid fa-trash"></i> Delete
                                    </button>
                                </form>
                            </td>
                        </tr>
                    @empty
                        <tr><td colspan="4" class="text-center">No products available.</td></tr>
                    @endforelse
                </tbody>
            </table>
      
            {!! $products->links() !!}
      </div>
    </div>
    @endsection
  3. Create Product Page

    File: resources/views/products/create.blade.php

    This view allows users to add a new product.

    @extends('products.layout')
    @section('content')
    <div class="card">
      <h2 class="card-header">Add New Product</h2>
      <div class="card-body">
        <div class="d-flex justify-content-end">
            <a class="btn btn-primary btn-sm" href="{{ route('products.index') }}">
                <i class="fa fa-arrow-left"></i> Back
            </a>
        </div>
        <form action="{{ route('products.store') }}" method="POST">
            @csrf
            <div class="mb-3">
                <label for="inputName" class="form-label"><strong>Name:</strong></label>
                <input type="text" name="name" class="form-control @error('name') is-invalid @enderror" id="inputName">
                @error('name')
                    <div class="text-danger">{{ $message }}</div>
                @enderror
            </div>
            <div class="mb-3">
                <label for="inputDetail" class="form-label"><strong>Detail:</strong></label>
                <textarea name="detail" class="form-control @error('detail') is-invalid @enderror" id="inputDetail"></textarea>
                @error('detail')
                    <div class="text-danger">{{ $message }}</div>
                @enderror
            </div>
            <button type="submit" class="btn btn-success">
                <i class="fa-solid fa-floppy-disk"></i> Submit
            </button>
        </form>
      </div>
    </div>
    @endsection
  4. Edit Product Page

    File: resources/views/products/edit.blade.php

    This view allows users to update a product.

    @extends('products.layout')
    @section('content')
    <div class="card">
      <h2 class="card-header">Edit Product</h2>
      <div class="card-body">
        <div class="d-flex justify-content-end">
            <a class="btn btn-primary btn-sm" href="{{ route('products.index') }}">
                <i class="fa fa-arrow-left"></i> Back
            </a>
        </div>
        <form action="{{ route('products.update', $product->id) }}" method="POST">
            @csrf
            @method('PUT')
            <div class="mb-3">
                <label for="inputName" class="form-label"><strong>Name:</strong></label>
                <input type="text" name="name" value="{{ $product->name }}" class="form-control @error('name') is-invalid @enderror" id="inputName">
                @error('name')
                    <div class="text-danger">{{ $message }}</div>
                @enderror
            </div>
            <div class="mb-3">
                <label for="inputDetail" class="form-label"><strong>Detail:</strong></label>
                <textarea name="detail" class="form-control @error('detail') is-invalid @enderror" id="inputDetail">{{ $product->detail }}</textarea>
                @error('detail')
                    <div class="text-danger">{{ $message }}</div>
                @enderror
            </div>
            <button type="submit" class="btn btn-success">
                <i class="fa-solid fa-floppy-disk"></i> Update
            </button>
        </form>
      </div>
    </div>
    @endsection
  5. Show Product Page

    File: resources/views/products/show.blade.php

    This view displays the details of a single product.

    @extends('products.layout')
    @section('content')
    <div class="card">
      <h2 class="card-header">Product Details</h2>
      <div class="card-body">
        <div class="d-flex justify-content-end">
            <a class="btn btn-primary btn-sm" href="{{ route('products.index') }}">
                <i class="fa fa-arrow-left"></i> Back
            </a>
        </div>
        <div class="mt-3">
            <strong>Name:</strong> <br/>
            {{ $product->name }}
        </div>
        <div class="mt-3">
            <strong>Details:</strong> <br/>
            {{ $product->detail }}
        </div>
      </div>
    </div>
    @endsection

Step 9: Run Laravel App

Once you have completed all the steps, you can now start the Laravel development server by running the following command in your terminal:

php artisan serve

Access Your Application

Now, open your browser and enter the following URL:

http://localhost:8000/products

You will see layout bellow:

Output:

List Page:

laravel 12 crud list page

Add Page:

Edit Page:

laravel 12 crud edit page

Show Page:

laravel 12 crud show page

I hope it can help you...

Tags

Do you Like?