Introduction
Laravel 11 is the latest version of the popular PHP framework, offering enhanced performance, cleaner syntax, and improved features. One of the core functionalities in any web application is CRUD (Create, Read, Update, Delete) operations. These operations allow users to interact with a database seamlessly.
In this tutorial, we will cover CRUD operations in Laravel 11 with a focus on listing, updating, and deleting records. We will use Laravel’s built-in features such as Eloquent ORM, Blade templates, and route model binding to make our development process smooth and efficient.
By the end of this tutorial, you will have a solid understanding of how to perform CRUD operations in Laravel 11 with a practical example.
Setting Up Laravel 11
Before starting, make sure you have Laravel 11 installed. If not, install it using Composer:
composer create-project --prefer-dist laravel/laravel laravel11crud
Navigate to your project directory:
cd laravel11crud
Creating a Model and Migration
We need a database table to store data. Let’s create a model along with a migration:
php artisan make:model Product -m
Open the generated migration file in database/migrations/
and update the up
method:
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->decimal('price', 8, 2);
$table->timestamps();
});
}
Run the migration to create the table:
php artisan migrate
Creating the Product Model
Modify the Product.php
model located in app/Models/Product.php
:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = ['name', 'description', 'price'];
}
This model allows mass assignment for name
, description
, and price
fields.
Creating a Controller
Generate a controller for handling CRUD operations:
php artisan make:controller ProductController --resource
This will create a ProductController.php
file in the app/Http/Controllers
directory.
Listing Records
Modify the index
method in ProductController.php
to retrieve and display products:
public function index()
{
$products = Product::all();
return view('products.index', compact('products'));
}
create a layout folder and then ap.blade.php and put this code
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>@yield(‘title’, ‘Laravel 11 CRUD’)</title>
<link rel=”stylesheet” href=”https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css”>
</head>
<body>
<nav class=”navbar navbar-expand-lg navbar-light bg-light”>
<div class=”container”>
<a class=”navbar-brand” href=”{{ route(‘products.index’) }}”>Laravel 11 CRUD</a>
<button class=”navbar-toggler” type=”button” data-bs-toggle=”collapse” data-bs-target=”#navbarNav” aria-controls=”navbarNav” aria-expanded=”false” aria-label=”Toggle navigation”>
<span class=”navbar-toggler-icon”></span>
</button>
<div class=”collapse navbar-collapse” id=”navbarNav”>
<ul class=”navbar-nav”>
<li class=”nav-item”>
<a class=”nav-link” href=”{{ route(‘products.index’) }}”>Products</a>
</li>
<li class=”nav-item”>
<a class=”nav-link” href=”{{ route(‘products.create’) }}”>Add Product</a>
</li>
</ul>
</div>
</div>
</nav>
<div class=”container mt-4″>
@yield(‘content’)
</div>
<script src=”https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js”></script>
</body>
</html>
Create a Blade template for listing products in resources/views/products/index.blade.php
:
@extends('layouts.app')
@section('content')
<h1>Product List</h1>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Actions</th>
</tr>
@foreach ($products as $product)
<tr>
<td>{{ $product->id }}</td>
<td>{{ $product->name }}</td>
<td>{{ $product->description }}</td>
<td>${{ $product->price }}</td>
<td>
<a href="{{ route('products.edit', $product->id) }}">Edit</a>
<form action="{{ route('products.destroy', $product->id) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit">Delete</button>
</form>
</td>
</tr>
@endforeach
</table>
@endsection
Updating a Record
Modify the edit
and update
methods in ProductController.php
:
public function edit(Product $product)
{
return view('products.edit', compact('product'));
}
public function update(Request $request, Product $product)
{
$request->validate([
'name' => 'required',
'description' => 'required',
'price' => 'required|numeric',
]);
$product->update($request->all());
return redirect()->route('products.index')->with('success', 'Product updated successfully');
}
create blade.php
@extends(‘layouts.app’)
@section(‘title’, ‘Create Product’)
@section(‘content’)
<div class=”container”>
<h1 class=”mt-4″>Create Product</h1>
<form action=”{{ route(‘products.store’) }}” method=”POST”>
@csrf
<div class=”mb-3″>
<label for=”name” class=”form-label”>Product Name</label>
<input type=”text” class=”form-control” id=”name” name=”name” required>
</div>
<div class=”mb-3″>
<label for=”description” class=”form-label”>Description</label>
<textarea class=”form-control” id=”description” name=”description” rows=”3″ required></textarea>
</div>
<div class=”mb-3″>
<label for=”price” class=”form-label”>Price</label>
<input type=”number” class=”form-control” id=”price” name=”price” step=”0.01″ required>
</div>
<button type=”submit” class=”btn btn-primary”>Create</button>
</form>
</div>
@endsection
Create an edit form in resources/views/products/edit.blade.php
:
@extends('layouts.app')
@section('content')
<h1>Edit Product</h1>
<form action="{{ route('products.update', $product->id) }}" method="POST">
@csrf
@method('PUT')
<input type="text" name="name" value="{{ $product->name }}" required>
<textarea name="description" required>{{ $product->description }}</textarea>
<input type="number" name="price" value="{{ $product->price }}" required>
<button type="submit">Update</button>
</form>
@endsection
Deleting a Record
Modify the destroy
method in ProductController.php
:
public function destroy(Product $product)
{
$product->delete();
return redirect()->route('products.index')->with('success', 'Product deleted successfully');
}
The delete button is already included in the listing table inside the index.blade.php
file.
Here is the complete controller code:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$products = Product::all();
return view(‘products.index’, compact(‘products’));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view(‘products.create’);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate([
‘name’ => ‘required’,
‘description’ => ‘required’,
‘price’ => ‘required|numeric’,
]);
Product::create($request->all());
return redirect()->route(‘products.index’)->with(‘success’, ‘Product created successfully’);
}
/**
* Display the specified resource.
*/
public function show(Product $product)
{
return view(‘products.show’, compact(‘product’));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Product $product)
{
return view(‘products.edit’, compact(‘product’));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Product $product)
{
$request->validate([
‘name’ => ‘required’,
‘description’ => ‘required’,
‘price’ => ‘required|numeric’,
]);
$product->update($request->all());
return redirect()->route(‘products.index’)->with(‘success’, ‘Product updated successfully’);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Product $product)
{
$product->delete();
return redirect()->route(‘products.index’)->with(‘success’, ‘Product deleted successfully’);
}
}
Defining Routes
Update the routes/web.php
file to include resource routes:
use App\Http\Controllers\ProductController;
Route::resource('products', ProductController::class);
Required Blade Files
Ensure you have the following Blade files in resources/views/products/
:
index.blade.php
– Lists products with edit and delete options.edit.blade.php
– Provides a form for editing a product.create.blade.php
(if adding create functionality) – Provides a form for adding a new product.layouts/app.blade.php
– A layout file that contains common structure and styling.
Summary
In this tutorial, we covered Laravel 11 CRUD operations, focusing on listing, updating, and deleting records. We:
- Created a model and migration for storing products
- Defined the
Product
model with mass assignable fields - Built a controller to handle CRUD operations
- Developed Blade templates for displaying and managing products
- Implemented update and delete functionalities
- Listed all required Blade files
By following these steps, you now have a fully functional Laravel 11 CRUD system. You can further enhance it by adding validation, authentication, and UI improvements using frameworks like Tailwind CSS or Bootstrap.
Happy coding!