Laravel 11 CRUD Application Example Tutorial
Greetings! Welcome to this tutorial where I’ll guide you through creating a Laravel 11 CRUD operation example step by step.
Before we dive in, let’s understand the meaning of CRUD: It’s an acronym from the world of computer programming, representing the four essential functions for persistent storage in your application: Create, Read, Update, and Delete.
In this example, we’ll build a note CRUD application using Laravel 11. We’ll create a notes table with name and content columns using Laravel migration. Then, we’ll set up routes, a controller, views, and model files for the note module. For design, we’ll use Bootstrap 5.
Let’s get started with the steps:
Step 1:
Install Laravel 11
Step 1: Laravel 11 Installation
To get started with Laravel 11, let’s create a fresh application named “my-laravel-app” using the command below. Open your terminal or command prompt and execute the following:
composer create-project laravel/laravel my-laravel-app
This command will generate a new Laravel 11 project named “my-laravel-app,” providing us with a clean starting point for our development journey.
Step 2:
Configuring MySQL Database
By default, Laravel 11 utilizes SQLite as its database connection. However, if you prefer MySQL, let’s configure it by adding the necessary details to your .env
file.
Replace your_mysql_host
with the hostname or IP address of your MySQL server, your_mysql_port
with the port number (typically 3306), your_database_name
with the name of your database, your_database_username
with your MySQL username, and your_database_password
with your MySQL password. This ensures Laravel connects to your MySQL database correctly.
Step 3:
Step 3: Creating Migration for Notes
In this step, we’ll generate a migration file to create a “notes” table with “title” and “content” columns using Laravel migration. Run the following command to create the migration file:
php artisan make:migration create_notes_table --create=notes
Upon executing the command, you’ll locate the migration file in the “database/migrations” directory. Insert the following code into your migration file to define the structure of the notes table:
<?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('notes', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('notes');
}
};
Now, execute the migration using the following command:
php artisan migrate
Step 4:
Generating Form Request Validation Class
Let's generate a form request validation class for the store()
and update()
methods in the controller. Run the following command to create the validation class:
php artisan make:request NoteStoreRequest
Now, insert the provided code into your request class:
app/Http/Requests/NoteStoreRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class NoteStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'title' => 'required|string|max:255',
'content' => 'required|string',
];
}
}
Let’s create the request class for updating a note. Run the following command to generate the update request class:
php artisan make:request NoteUpdateRequest
Now, add the provided code into your request class:
app/Http/Requests/NoteUpdateRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class NoteUpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'title' => 'required|string|max:255',
'content' => 'required|string',
];
}
}
Step 5:
Creating Controller and Model
Let’s generate a new resource controller named NoteController along with its corresponding model Note. Execute the following command to create the controller:
artisan make:controller NoteController --resource --model=Note
Once the command is executed, you’ll find a new file located at “app/Http/Controllers/NoteController.php”. This controller automatically generates seven methods for handling CRUD operations:
- index()
- create()
- store()
- show()
- edit()
- update()
- destroy()
Now, let’s paste the generated code into the NoteController.php file
<?php
namespace App\Http\Controllers;
use App\Models\Note;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;
use App\Http\Requests\NoteStoreRequest;
use App\Http\Requests\NoteUpdateRequest;
class NoteController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(): View
{
$notes = Note::latest()->paginate(5);
return view('notes.index', compact('notes'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('notes.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(NoteStoreRequest $request): RedirectResponse
{
Note::create($request->validated());
return redirect()->route('notes.index')
->with('success', 'Note created successfully.');
}
/**
* Display the specified resource.
*/
public function show(Note $note): View
{
return view('notes.show', compact('note'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Note $note): View
{
return view('notes.edit', compact('note'));
}
/**
* Update the specified resource in storage.
*/
public function update(NoteUpdateRequest $request, Note $note): RedirectResponse
{
$note->update($request->validated());
return redirect()->route('notes.index')
->with('success', 'Note updated successfully');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Note $note): RedirectResponse
{
$note->delete();
return redirect()->route('notes.index')
->with('success', 'Note deleted successfully');
}
}
So, let’s update the Note model code as follows:
app/Models/Note.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Note extends Model
{
use HasFactory;
protected $fillable = [
'title',
'content',
];
}
Step 7:
Update AppServiceProvider
In this step, we’ll import Bootstrap 5 for pagination in the AppServiceProvider.php file. Let’s proceed with the update:
app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Paginator::useBootstrap();
}
}
Step 8:
Adding Blade Files
In this step, we need to create several blade files for our CRUD application. First, create a layout file named “layout.blade.php”. Then, within a new folder named “notes”, create the following blade files:
- layout.blade.php
- index.blade.php
- create.blade.php
- edit.blade.php
- show.blade.php
Now, let’s proceed with creating these files and adding the corresponding code to each of them.
resources/views/notes/layout.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel CRUD Application</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">
@yield('content')
</div>
</body>
</html>
resources/views/notes/index.blade.php
@extends('notes.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Laravel CRUD Example</h2>
<div class="card-body">
@if(session('success'))
<div class="alert alert-success" role="alert">{{ session('success') }}</div>
@endif
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-success btn-sm" href="{{ route('notes.create') }}"><i class="fa fa-plus"></i> Create New Note</a>
</div>
<table class="table table-bordered table-striped mt-4">
<thead>
<tr>
<th width="80px">No</th>
<th>Name</th>
<th>content</th>
<th width="250px">Action</th>
</tr>
</thead>
<tbody>
@forelse ($notes as $note)
<tr>
<td>{{ ++$i }}</td>
<td>{{ $note->name }}</td>
<td>{{ $note->content }}</td>
<td>
<form action="{{ route('notes.destroy',$note->id) }}" method="POST">
<a class="btn btn-info btn-sm" href="{{ route('notes.show',$note->id) }}"><i class="fa-solid fa-list"></i> Show</a>
<a class="btn btn-primary btn-sm" href="{{ route('notes.edit',$note->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">There are no data.</td>
</tr>
@endforelse
</tbody>
</table>
{!! $notes->links() !!}
</div>
</div>
@endsection
resources/views/notes/create.blade.php
@extends('notes.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Add New Note</h2>
<div class="card-body">
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-primary btn-sm" href="{{ route('notes.index') }}"><i class="fa fa-arrow-left"></i> Back</a>
</div>
<form action="{{ route('notes.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"
placeholder="Name">
@error('name')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="inputcontent" class="form-label"><strong>content:</strong></label>
<textarea
class="form-control @error('content') is-invalid @enderror"
style="height:150px"
name="content"
id="inputcontent"
placeholder="content"></textarea>
@error('content')
<div class="form-text 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
resources/views/notes/edit.blade.php
@extends('notes.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Edit Note</h2>
<div class="card-body">
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-primary btn-sm" href="{{ route('notes.index') }}"><i class="fa fa-arrow-left"></i> Back</a>
</div>
<form action="{{ route('notes.update',$note->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="{{ $note->name }}"
class="form-control @error('name') is-invalid @enderror"
id="inputName"
placeholder="Name">
@error('name')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="inputcontent" class="form-label"><strong>content:</strong></label>
<textarea
class="form-control @error('content') is-invalid @enderror"
style="height:150px"
name="content"
id="inputcontent"
placeholder="content">{{ $note->content }}</textarea>
@error('content')
<div class="form-text 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
resources/views/notes/show.blade.php
@extends('notes.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Show Note</h2>
<div class="card-body">
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-primary btn-sm" href="{{ route('notes.index') }}"><i class="fa fa-arrow-left"></i> Back</a>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Name:</strong> <br/>
{{ $note->name }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 mt-2">
<div class="form-group">
<strong>contents:</strong> <br/>
{{ $note->content }}
</div>
</div>
</div>
</div>
</div>
@endsection
To run the Laravel app, execute the following command and hit enter:
php artisan serve
Then, navigate to your web browser and enter the following URL to view the app output:
http://localhost:8000
Conclusion:
In conclusion, we’ve successfully set up a Laravel application to manage notes. We installed Laravel 11, configured MySQL database, created migration for the notes table, implemented form request validation, generated a resource controller and model for the notes, added blade files for CRUD operations, and updated the AppServiceProvider for pagination. With these steps completed, our Laravel application is now ready for use to manage notes effectively.