HomeLaravelLaravel 12 CRUD Application Example Tutorial

Laravel 12 CRUD Application Example Tutorial

laravel 12 crud application example

This article with guide you to create a Laravel 12 CRUD application example. You will be able to create, update, view and delete product from database with Laravel 12 PHP MVC framework.

Steps to Create Laravel 12 CRUD Application

You need to follow the step to create laravel CRUD application.

  • install PHP
  • install Composer
  • create and run Laravel project
  • setup Database
  • create Model and run database migration
  • create Controller
  • create Routes for Controller Resource
  • create View
  • add custom CSS

Install PHP

Ensure that at least PHP 8.2 is installed on your system. You can install PHP using XAMPP 8.2 or other methods depending on your operating system. XAMPP has also MySQL database, Apache Server and phpMyAdmin preconfigured, which will be require for Laravel 12 CRUD application development. XAMPP provides you the AMP stack. AMP stands for Apache, MySQL, and, PHP.

Install Composer

Download Composer from getcomposer.org, which is a dependency manager for PHP. Follow the installation instructions to set up Composer on your system.

Create a New Laravel Project

Once PHP, MySQL, Apache (XAMPP) and Composer are installed, you can create a new Laravel project in the PHP projects directory of XAMPP, it might be C:\xampp\htdocs. Run the following composer command in your terminal or CMD at C:\xampp\htdocs path or whichever is the appropriate path for PHP codes.


C:\xampp\htdocs

composer create-project laravel/laravel:^12.0 laravel-product-crud


This command will create a new Laravel project called laravel-product-crud with Laravel 12 version.

Start Laravel Development Server

Navigate to your project directory laravel-product-crud and start Laravel’s local development server using Artisan’s serve command:

C:\xampp\htdocs

cd laravel-product-crud
php artisan serve

Your laravel 12 application can be accessed from the browser at http://localhost:8000

Set Up the Database

Open laravel-product-crud folder or directory in your code editor such as Visual Studio Code/PhpStorm/WebStorm/Notepad++. Then open .env and configure your database connection (e.g., MySQL). We will use MySQL database because XAMPP ships with MySQL and also in production serever, MySQL or MariaDB is mostly used. However, you’re free to use the default SQLite database in .env file of Laravel. Now remove or comment out the SQLite database connection configuration and add this MySQL configuration in the .env file.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_product_crud
DB_USERNAME=root
DB_PASSWORD=
DB_COLLATION=utf8mb4_unicode_ci

This will make a MySQL database connection for the Laravel 12 CRUD application with
databasename: laravel_product_crud, username: root and without any password. You will get this username:root and password:”” from the default XAMPP setup.

Now, you need to create the actual MySQL database in XAMPP with phpMyAdmin. So head over to
http://localhost/phpmyadmin and create laravel_product_crud database from phpMyAdmin.
Now your laravel 12 application is ready for database migration. In Laravel, database migration is a process that creates SQL database schema for the database from your Laravel Application.

Create MySQL database table with phpMyAdmin using XAMPP.

Create the Model and Migration

Run the Laravel Artisan command to generate a model with a migration:
To implement a CRUD (Create, Read, Update, Delete) functionality for a post schema in Laravel 11, you can follow these steps based on the provided sources:

Define Post Schema: Define the schema for your post model. This typically involves creating a migration file to define the structure of your database table as php artisan serve command is running on the current CMD, open a new CMD and cd to

C:\xampp\htdocs\laravel_product_crud and then run

php artisan make:migration create_posts_table

The next all CMD commands can be run from the 2nd CMD prompt while keep the 1st CMD running with php artisan serve command.

Generate Model and Migration: To generate a model and migration for your products schema use the following command. This will create app/Models/Product.php to define your Product model and its corresponding database migration file database/migrations/2025_02_21_xxxxxx_create_products_table.php with -m flag.

php artisan make:model Product -m

Define the Schema: Open the generated migration file in database/migrations/2025_02_21_xxxxxx_create_products_table.php and define the schema:

<?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()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('description')->nullable();
            $table->decimal('price', 8, 2);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

The up() function will create a products table with id, name, description, price, created_at, updated_at columns in the database that was created with phpMyAdmin earlier. $table->timestamps() is responsible for creating both created_at and updated_at columns.

Now if the database connection configuration and everything is fine then you will be able to run migration with this Laravel php artisan command

php artisan migrate

Update the Product model app/Models/Product.php to make fields fillable:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = ['name', 'description', 'price'];
}


The $fillable = [‘name’, ‘description’, ‘price’] will allow only read and write operation in name, description, price columns of products MySQL database table. By following these steps you have created the model of the MVC framework.

Create the Controller

Follow these steps you have created the the controller of the MVC framework.

Generate a resourceful controller for CRUD operations:

php artisan make:controller ProductController --resource

This will generate the Product controller file for the Product model in app/Http/Controllers/ProductController.php which will have the following empty methods to hold the following logic:

  • index() for running ORM logic of SELECT * FROM products and index blade view
  • create() for loading create form blade view
  • store() for running ORM logic of INSERT INTO products
  • show($product_id) for running ORM logic of SELECT * FROM products WHERE id=$product_id SQL
  • edit($product_id) for running ORM logic of SELECT * FROM products WHERE id=$product_id SQL and load this into the edit form
  • update($product_id) for running ORM logic of UPDATE products SET… WHERE id=$product_id SQL
  • destroy($product_id) for running ORM logic of DELETE FROM products WHERE id=$product_id SQL

Now update the ProductController.php with this code which is the laravel framework specific codes with Eloquent ORM to transform the logic above.

<?php

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::all();
        return view('products.index', compact('products'));
    }

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

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

        Product::create($request->all());
        return redirect()->route('products.index')->with('success', 'Product created successfully.');
    }

    public function show(Product $product)
    {
        return view('products.show', compact('product'));
    }

    public function edit(Product $product)
    {
        return view('products.edit', compact('product'));
    }

    public function update(Request $request, Product $product)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'price' => 'required|numeric|min:0',
            'description' => 'nullable|string',
        ]);

        $product->update($request->all());
        return redirect()->route('products.index')->with('success', 'Product updated successfully.');
    }

    public function destroy(Product $product)
    {
        $product->delete();
        return redirect()->route('products.index')->with('success', 'Product deleted successfully.');
    }
}

Define Routes

Open routes/web.php and add the resourceful route for products:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;

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

Route::resource('products', ProductController::class);

This creates routes for all CRUD operations (e.g., /products, /products/create, /products/{id} etc.).

Create Views

Create a resources/views/products/ directory and add the following Blade files. Note, Laravel does not provide any artisan command to generate blade view file, so you need to create each blade file from your code editor manually. Blade is a special PHP file type which has .blade.php extension. It is a template engine file for view of the MVC application by Laravel. Create resources/views/products/index.blade.php, resources/views/products/create.blade.php, resources/views/products/edit.blade.php, resources/views/products/show.blade.php files with your code editor and add the following codes.

resources/views/products/index.blade.php (List all products) (R = Read and, D = Delete of CRUD)

<!DOCTYPE html>
<html>
<head>
    <title>Products</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Products</h1>
        @if (session('success'))
            <div class="alert alert-success">{{ session('success') }}</div>
        @endif
        <a href="{{ route('products.create') }}" class="btn btn-primary">Add Product</a>
        <table class="table">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Price</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                @foreach ($products as $product)
                    <tr>
                        <td>{{ $product->id }}</td>
                        <td>{{ $product->name }}</td>
                        <td>{{ $product->price }}</td>
                        <td>
                            <a href="{{ route('products.show', $product) }}" class="btn btn-info">View</a>
                            <a href="{{ route('products.edit', $product) }}" class="btn btn-warning">Edit</a>
                            <form action="{{ route('products.destroy', $product) }}" method="POST" style="display:inline;">
                                @csrf
                                @method('DELETE')
                                <button type="submit" class="btn btn-danger" onclick="return confirm('Are you sure?')">Delete</button>
                            </form>
                        </td>
                    </tr>
                @endforeach
            </tbody>
        </table>
    </div>
</body>
</html>

resources/views/products/create.blade.php (Add new product) (C = Create of CRUD)

<!DOCTYPE html>
<html>
<head>
    <title>Create Product</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Create Product</h1>
        <form action="{{ route('products.store') }}" method="POST">
            @csrf
            <div class="form-group">
                <label>Name</label>
                <input type="text" name="name" class="form-control" required>
            </div>
            <div class="form-group">
                <label>Description</label>
                <textarea name="description" class="form-control"></textarea>
            </div>
            <div class="form-group">
                <label>Price $</label>
                <input type="number" name="price" class="form-control" step="0.01" required>
            </div>
            <button type="submit" class="btn btn-success">Save</button>
            <a href="{{ route('products.index') }}" class="btn btn-secondary">Cancel</a>
        </form>
    </div>
</body>
</html>

resources/views/products/edit.blade.php (Edit product) (U= Update of CRUD)

<!DOCTYPE html>
<html>
<head>
    <title>Edit Product</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Edit Product</h1>
        <form action="{{ route('products.update', $product) }}" method="POST">
            @csrf
            @method('PUT')
            <div class="form-group">
                <label>Name</label>
                <input type="text" name="name" class="form-control" value="{{ $product->name }}" required>
            </div>
            <div class="form-group">
                <label>Description</label>
                <textarea name="description" class="form-control">{{ $product->description }}</textarea>
            </div>
            <div class="form-group">
                <label>Price $</label>
                <input type="number" name="price" class="form-control" step="0.01" value="{{ $product->price }}" required>
            </div>
            <button type="submit" class="btn btn-success">Update</button>
            <a href="{{ route('products.index') }}" class="btn btn-secondary">Cancel</a>
        </form>
    </div>
</body>
</html>

resources/views/products/show.blade.php (View product details)

<!DOCTYPE html>
<html>
<head>
    <title>Product Details</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>Product Details</h1>
        <p><strong>Name:</strong> {{ $product->name }}</p>
        <p><strong>Description:</strong> {{ $product->description ?? 'N/A' }}</p>
        <p><strong>Price:</strong> ${{ $product->price }}</p>
        <a href="{{ route('products.index') }}" class="btn btn-secondary">Back</a>
    </div>
</body>
</html>

Now save all the files you have created and added codes (i.e. from product migration file to blade view files). Up to now, you have completed all the necessary steps to run a fully functional laravel 12 CRUD application.


Run Laravel 12 CRUD Application

As you already have the php artisan serve command is running so all you need to do is point out your browser to see your fully functional Laravel 12 CRUD application at http://localhost:8000/products.

laravel 12 crud application example

Test the CRUD functionality by creating new product, updating and deleting the product.

Adding Custom CSS

Now you have a bare bone fully functional laravel CRUD application. It’s time to add some custom CSS, with Google font to provide better UX.
Create a file public/css/app.css and add the following CSS:

/* public/css/app.css */


@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');

body {
    font-family: "Nunito", serif;
    font-style: normal;
    font-weight: 400;
    font-size: 16px;
    line-height: 1.5;
    color: #333;
    background-color: #f4f4f4;
    margin: 0;
    padding: 0;
}

.container {
    width: 80%;
    margin: 20px auto;
    padding: 20px;
    background-color: #fff;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
}

h1 {
    color: #333;
    text-align: center;
}

.table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
}

.table th, .table td {
    padding: 10px;
    text-align: left;
    border-bottom: 1px solid #ddd;
}

.table th {
    background-color: #ddd;

}

.form-group {
    margin-bottom: 15px;
}

.form-group label {
    display: block;
    margin-bottom: 5px;
    color: #333;
}

.form-group input, .form-group textarea {
    width: 100%;
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    box-sizing: border-box;
}

.btn {
    display: inline-block;
    padding: 10px 20px;
    text-decoration: none;
    color: #fff;
    background-color: #1649ff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s;
    font-size: 16px;
    line-height: 1;
    min-width: 100px;
    text-align: center;
    box-sizing: border-box;
}

.btn:hover {
    background-color: #0d3ecc;
}

.btn-secondary {
    background-color: #666;
}

.btn-secondary:hover {
    background-color: #4d4d4d;
}

.btn-danger {
    background-color: #ff4d4d;
}

.btn-danger:hover {
    background-color: #cc0000;
}

.alert-success {
    padding: 10px;
    background-color: #d4edda;
    color: #155724;
    border: 1px solid #c3e6cb;
    border-radius: 4px;
    margin-bottom: 15px;
}

p {
    margin: 10px 0;
}

strong {
    font-weight: bold;
    color: #4d4d4d;
}

After creating app.css file you need to create a base layout which will contain the css/app.css file reference

resources/views/layouts/app.blade.php (Base Layout)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Laravel CRUD</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
</body>
</html>

Now you need to include the app layout into your all blade view files for custom CSS to be included, therefore make sure the following blade view files are like this with updated changes.

resources/views/products/index.blade.php (List Products)

@extends('layouts.app')

@section('content')
    <h1>Products</h1>
    @if (session('success'))
        <div class="alert-success">{{ session('success') }}</div>
    @endif
    <a href="{{ route('products.create') }}" class="btn">Add Product</a>
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Price</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($products as $product)
                <tr>
                    <td>{{ $product->id }}</td>
                    <td>{{ $product->name }}</td>
                    <td>{{ $product->price }}</td>
                    <td>
                        <a href="{{ route('products.show', $product) }}" class="btn">View</a>
                        <a href="{{ route('products.edit', $product) }}" class="btn">Edit</a>
                        <form action="{{ route('products.destroy', $product) }}" method="POST" style="display:inline;">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-danger" onclick="return confirm('Are you sure?')">Delete</button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>
@endsection

resources/views/products/create.blade.php (Create Product)

@extends('layouts.app')

@section('content')
    <h1>Create Product</h1>
    <form action="{{ route('products.store') }}" method="POST">
        @csrf
        <div class="form-group">
            <label>Name</label>
            <input type="text" name="name" class="form-control" required>
        </div>
        <div class="form-group">
            <label>Description</label>
            <textarea name="description" class="form-control"></textarea>
        </div>
        <div class="form-group">
            <label>Price $</label>
            <input type="number" name="price" class="form-control" step="0.01" required>
        </div>
        <button type="submit" class="btn">Save</button>
        <a href="{{ route('products.index') }}" class="btn btn-secondary">Cancel</a>
    </form>
@endsection

resources/views/products/edit.blade.php (Edit Product)

@extends('layouts.app')

@section('content')
    <h1>Edit Product</h1>
    <form action="{{ route('products.update', $product) }}" method="POST">
        @csrf
        @method('PUT')
        <div class="form-group">
            <label>Name</label>
            <input type="text" name="name" class="form-control" value="{{ $product->name }}" required>
        </div>
        <div class="form-group">
            <label>Description</label>
            <textarea name="description" class="form-control">{{ $product->description }}</textarea>
        </div>
        <div class="form-group">
            <label>Price $</label>
            <input type="number" name="price" class="form-control" step="0.01" value="{{ $product->price }}" required>
        </div>
        <button type="submit" class="btn">Update</button>
        <a href="{{ route('products.index') }}" class="btn btn-secondary">Cancel</a>
    </form>
@endsection

resources/views/products/show.blade.php (Show Product)

@extends('layouts.app')

@section('content')
    <h1>Product Details</h1>
    <p><strong>Name:</strong> {{ $product->name }}</p>
    <p><strong>Description:</strong> {{ $product->description ?? 'N/A' }}</p>
    <p><strong>Price:</strong> ${{ $product->price }}</p>
    <a href="{{ route('products.index') }}" class="btn">Back</a>
@endsection

Finally, visit http://localhost:8000/products to see the Laravel 12 CRUD app with custom styling.

Products page

Edit Product page

Products MySQL database table from phpMyAdmin provided by XAMPP

Hope this tutorial helps you develop a Laravel 12 Product CRUD application successfully.

Share: 

No comments yet! You be the first to comment.
Categories