In this comprehensive guide and tutorial in which you will learn how to create your first todo app on laravel step by step. We will be performing all 4 CRUD (Create Read Update and Delete) operations in laravel 9.
This is the Crash Course created keeping Beginners in mind so that they can follow along. In this tutorial, we will going to create todo app using Bootstrap 5 in laravel 9.
This tutorial can work on other version of laravel as well such laravel 8 and laravel 7.
Let’s get started!
Table of Contents
Prerequisites:
In order to learn and install laravel 9, there are some requirements which is must to have in order to understand properly. These requirements consists of technical requirements and the knowledge requirements.
Technical/System Requirements for laravel 9:
- You must have a minimum PHP 8.0 installed in your system for laravel 9
- Make sure you have installed the
composer
to install the laravel and PHP packages - MYSQL for the database
And Some of the PHP extensions:
These extensions of PHP are also required to install in order to work laravel properly:
- BCMath PHP Extension
- Ctype PHP Extension
- Fileinfo PHP extension
- JSON PHP Extension
- Mbstring PHP Extension
- OpenSSL PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
Knowledge Requirements for learning laravel:
In order to learn the laravel, some you must have knowledge of :
- PHP and its concepts (Beginner to Intermediate Level)
- OOP Concepts
- MYSQL Concepts
If you have good or above average knowledge of above, you are good to proceed.
What is Laravel?
Laravel is based on PHP framework which works on MVC (Model View Controller) that allow us to create web applications more seamlessly and securely. It provides also very easy to scale.
Being open-source framework, laravel not only has made the web development easy but also the community which they have build, continuously ships tons of new features and new packages on the frequent basis.
Due to those features, laravel framework is one of the most popular PHP framework.
What is MVC Architecture?
MVC Stands for Model, View and Controller.
Laravel is based on MVC Architecture which allow us to split the code in parts for better organization and keeping the code clean so that its always ready to scale for new features.
- Model is way of querying data to and from the table using database
- View basically contains the frontend of the application (HTML)
- Controller is responsible for satisfying request and contains the business logic
Step 1: Install Laravel
Let’s first install the laravel in laravel_crud
folder using terminal:
composer create-project --prefer-dist laravel/laravel laravel_crud
You will see something like this in the terminal:
It means the laravel framework has been successfully downloaded and installed.
Then open up the project in your favorite editor/IDE. I am using PHPStorm IDE. You will see the following files
Step 2: Update DB Credentials
Now go the .env
and change the DB_DATABASE
, DB_USERNAME
, DB_PORT
and DB_PASSWORD
according to your database details.
Step 3: Migrate Database
What is Laravel Migration?
Laravel migration is one of the laravel’s popular feature which let us create, modify and delete tables and its columns.
Laravel ships some of the migration files for some tables by default which includes users
, password resets
, failed_jobs
and personal_access_tokens
and migrations
tables.
Note: You can see that tables names are plural. Will explain later on why it is so when we create the modal.
And you can see them by going to database/migrations
folder:
How to migrate?
So now in order to convert that migration files to tables in the database, we run to migrate by using the following command in the terminal:
php artisan migrate
You will see the following output in the terminal:
And if you open the database you will see that your database will now have 5 tables which I have mentioned above:
Step 4: Run Application
Now in order to start application, you need to type following command in the terminal:
php artisan serve
You will see in the terminal that the application will get started and will give you URL to access it.
In my case, the access url is . If you type this in browser you will see following screen:
If you see the above screen, it means you have ran the laravel 9. Hurray!
Make sure the next command for terminal, you do in the another terminal, and dont close this terminal otherwise you have run again using php artisan serve
command.
Step 5: Create Migration for the todos table
Since we are creating the todo app, we need to create the todo
table, in which we will store all todo.
We will have the following columns in todo
table:
- title
- is_completed
Let’s create the migration file for the todo
table by typing the following command:
php artisan make:migration create_todos_table
This will create a new migration file in the database/migrations
folder with the name of create_todos_table.php
with some date prefix which will contains some 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.
*
* @return void
*/
public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('todos');
}
};
The up()
the function is basically the function where we create the table and as you can see that some code is already written for the todos
table and you can see the id()
and timestamps()
.
Theid()
and timestamps()
are columns that automatically get added when we have created the migration file. Those columns can be removed if want, but i will keep them in this case.
Now lets add the title
and is_completed
columns.
The final up()
function will look like this:
public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->id();
$table->longText('title');
$table->boolean('is_completed')->default(0);
$table->timestamps();
});
}
We added the title
as the longText
and is_completed
as boolean
with the default value of 0. We will consider 0 as the not completed and 1 as the completed.
Now you need to migrate again by using following command:
php artisan migrate
You will see that your todos
table is migrated now.
Step 6: Create Model for the todos table
What is a Model in laravel?
Model in laravel is a way of querying data to and from the table within the database.
How to Create a Model?
Since we want to create model for our todos
table, we will create that by using following command:
php artisan make:model Todo
This will create the Todo
Model for our todos
table.
Note: You can see that model name is Singular (Todo) where as the migration and the table name is Plural (todos), this is how the laravel recommends the naming scheme should be.
Now if you go to the app/Models
you will see that Todo
Model is now gets created.
Setting up the model:
If you open that up, you will see something like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Todo extends Model
{
use HasFactory;
}
Now after use HasFactory;
type:
protected $guarded=[];
You can see that in $guarded
variable, we have added an empty array.
This means don’t allow the columns values to get changed or added which we have mentioned in the array.
But since we haven’t added any column in the array, all column values can get changed.
Step 7: Create Controller and Route
What is a Controller in laravel?
A Controller controls the behavior of the request. It accepts request coming from the route and satisfy them.
In the controller, we usually write all of our business logic. Usually, we validate the request and then fetching data from the database using model
How to Create Controller ?
In order to create controller for our Todo
Model or todos
table, you need to type the following command:
php artisan make:Controller TodoController --resource
You will see something like this:
This will allow us to create the controller, where as --resource
is to declare as the resource which create some empty functions like index
, create
, store
, show
, edit
, update
anddestroy
to save time that we will use these functions to add our business logic to make CRUD operation.
What is a Route in laravel?
Route is a way of requesting data from end users. The route is usually tied with controller function.
In simple terms it means that if the user types this in URL execute that controller funtion which is tied to that route.
How to Create Route?
In order to create the route as the resource, go to routes/web.php
file and at the end of the file write:
Route::resource('todos', \App\Http\Controllers\TodoController::class);
This will now allow us to access all the functions of the TodoController
.
How to see all the Routes?
If you want to see, all the able routes you can type the following command in the terminal:
php artisan route:list
You will be able to see all the available routes for our application.
You can see that we have a bunch of route endpoints, and we will use a few of them only for now in this application.
- todos.index
GET
method with index funtion, we will use to fetch and load of all todos. It will also contains add todo view. - todos.store
POST
method with store function, we will have the logic of adding todo. - todos.edit
GET
method with edit function, we will use to fetch and load the view of edit todo. - todos.update
PUT
method with update function, we will use to update the todo. - todos.delete
DELETE
method with delete function, we will use to delete the todo.
Other than above routes, we will not be using in this tutorial.
Step 8: Create View File
What is View in Laravel?
The view usually contains all the frontend of the application aka HTML.
Laravel framework provides out of the box blade templating engine that’s helps to write HTML, PHP code easy to write plus provides tons of features.
How to create View in Laravel?
Since we want to create todo
app, we will have two files.
In todo.blade.php
, on the top we will have the add todo functionality and bottom we will display all the todos items.
In edit-todo.blade.php
, we will load the existing todo title
and status
and allow you to change that.
Let’s create those two files now. Since there is no method to create view files via command, we have to manually go to resources/views the folder and create those files with the name of todo.blade.php
and edit-todo.blade.php
file.
Now let’s add the bootstrap 5 boilerplate in the both todo.blade.php
and edit-todo.blade.php
file.
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>
After that add the following code in both files after the body opening tag:
<div class="row justify-content-center mt-5">
<div class="col-lg-6">
@if(session()->has('success'))
<div class="alert alert-success">
{{ session()->get('success') }}
</div>
@endif
@if ($errors->any())
@foreach ($errors->all() as $error)
<div class="alert alert-danger">
{{$error}}
</div>
@endforeach
@endif
</div>
</div>
The above code is nothing more but for capturing the errors and success messages.
You can see that we are using the if
and foreach
conditions that which blade templating engine provides out of the box to use PHP keywords directly in the HTML.
Whereas {{ }}
is blade reversed keyword used to echo/ print something.
How cool it is that we write PHP code with HTML in a clean way.
When we access the controller function which contains the view. The blade engine renders that view into native PHP code and HTML code and shows us the output.
Cool now in the index
function of app/Http/Controllers/TodoController
link that todo.blade.php
view file we created:
public function index()
{
//
return view('todo');
}
Now if you visit the http://127.0.0.1:8000/todos
in browser, you will see the Hello World.
Step 9: Lets write code for Create Operation
To do the create operation:
A) We need a form with the submit button in our todo.blade.php
file.
B) Then that form will basically link that form to our POST
route which is linked store
function of the TodoController
where will add the logic to store the todo in the database.
Don’t worry! If you don’t understand the above flow. You will be able to understand once we are doing it.
A) Create a form for collecting todo
In the todo.blade.php
after the body opening tag add the following code for creating the form:
<div class="text-center mt-5">
<h2>Add Todo</h2>
<form class="row g-3 justify-content-center" method="POST" action="{{route('todos.store')}}">
@csrf
<div class="col-6">
<input type="text" class="form-control" name="title" placeholder="Title">
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-3">Submit</button>
</div>
</form>
</div>
In the above code, you can see that we have added the text field and a button in the form.
Form method set to POST
and action
url to {{route('todos.store')}}
.
Whereas the route
keyword is used to access the route we want to link to.
In this case, we need to send request to the store
function of TodoController
which can be accessed by typing todos.store
if you see the below screenshot.
If you open the http://127.0.0.1:8000/todos
in the browser, you will see something like this:
B) Create a form for collecting todo
Now lets go to store
function of the TodoController
and add the following code:
public function store(Request $request)
{
//
$validator = Validator::make($request->all(), [
'title' => 'required',
]);
if ($validator->fails())
{
return redirect()->route('todos.index')->withErrors($validator);
}
Todo::create([
'title'=>$request->get('title')
]);
return redirect()->route('todos.index')->with('success', 'Inserted');
}
In the above code, first we are validating the request using Laravel Validator
functionality. We are validating that title
is required
always.
If it’s not present, return to route('todos.index')
which is the main page of our application with the error.
If its present, then we are calling the Todo
Model we created before with the create
function to store the todo in the table of todos
.
You can see that in create
we have also passed title
which have getting from the $request
which contains all the variables passed to this function.
Note: Make sure to include the includes at the top of the TodoController.php file
use App\Models\Todo;
This will allow use to use the Todo Model
use Illuminate\Support\Facades\Validator;
This will allow us to use the Laravel Validator
So now if you don’t type anything in title
and submit, you will see this error:
If you type something in title field, you will see this success message:
Which means that the todo is instead into the todos
table.
Hurray! You have successfully completed your first operation of creating Todo.
Step 10: Lets write code for Read Operation
In the Read operation, we want to display all the todo we have in todos
table.
A) First we will get all the todos
in our index
function of TodoController
.
B) Then we will show all the todos
in our todos.blade.php
.
A) Get All todos in index function of TodoController
We need to get all the todos
in our index
function of TodoController
. So we need to update our index
function:
public function index()
{
//
$todos=Todo::all();
return view('todo',compact('todos'));
}
In the above code using the Todo
Model, we are getting all the todos using all()
function and storing them in $todos
variable.
Then we are passing out the that todos
variable to the view using compact
.
The compact
accept variable as the string itself.
Now the todo.blade.php
, will have access to the all the todos.
B) Show all the todos
in our todos.blade.php
In the todos.blade.php
file, after the add todo code, add the following code:
<div class="text-center">
<h2>All Todos</h2>
<div class="row justify-content-center">
<div class="col-lg-6">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Created at</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
@php $counter=1 @endphp
@foreach($todos as $todo)
<tr>
<th>{{$counter}}</th>
<td>{{$todo->title}}</td>
<td>{{$todo->created_at}}</td>
<td>
@if($todo->is_completed)
<div class="badge bg-success">Completed</div>
@else
<div class="badge bg-warning">Not Completed</div>
@endif
</td>
<td>
<a class="btn btn-info">Edit</a>
<a class="btn btn-danger">Delete</a>
</td>
</tr>
@php $counter++; @endphp
@endforeach
</tbody>
</table>
</div>
</div>
</div>
In the above code, first I have created the Bootstrap table, then created $counter
variable using @php
blade variable which allow us to write the PHP code.
Then we are looping through each todos
(which have passed through the index
function to the todos.blade.php
in the Step A) using foreach
PHP function.
You can see that we are loading the title
of the todo item by $todo->title
.
Then we have conditional rendering for the status that if $todo->is_completed
is 1 then show complete and if its 0 then show not complete.
In the end of the table, we are incrementing the counter itself by using $counter++
.
If you open the http://127.0.0.1:8000/todos
in browser, you will see something like this:
This means it showing all the todos we have in the database.
Step 11: Lets write code for Update Operation
To do an update operation:
A) First, we will change the URL of edit button in todos.blade.php
.
B) Then, we link that view with edit
function of TodoController
with view edit-todo.blade.php
.
C) Then, in edit-todo.blade.php
we will create the form with title
and status
field in which we load the existing value and the user will be able to edit the title
and status
.
D) In update
function, add logic for validation and updating the Todo
.
A) Change URL of edit button in todos.blade.php
First of all, we need to change the edit button to following code in todos.blade.php
.
<a href="{{route('todos.edit',['todo'=>$todo->id])}}" class="btn btn-info">Edit</a>
In the above code, we are changing the edit button in todos.blade.php
to able to call the edit
function in which we are passing the todo id
which we want to edit.
B) Link Edit function with edit-todo.blade.php
In this step, we will link the edit
function of TodoController
to edit-todo.blade.php
file. Add the following code in the edit
function:
public function edit($id)
{
//
$todo=Todo::where('id',$id)->first();
return view('edit-todo',compact('todo'));
}
In the edit
function, you can see that we have id
being passed, that id will be basically id
of the todo item which details we want to load.
So we need to get data of that Todo
using that id
and that’s what we dong in the very first line of the edit
function in the above code and storing it into $todo
variable.
Then we passed that todo
to the edit-todo.blade.php
.
C) Create a form in edit-todo.blade.php
In this step, we will create the form in the edit-todo.blade.php
. And we will link the form action with update
function of TodoController
.
We will add the following code after the starting tag of body
:
<div class="text-center mt-5">
<h2>Edit Todo</h2>
</div>
<form method="POST" action="{{route('todos.update',['todo'=>$todo->id])}}">
@csrf
{{ method_field('PUT') }}
<div class="row justify-content-center mt-5">
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Title</label>
<input type="text" class="form-control" name="title" placeholder="Title" value="{{$todo->title}}">
</div>
<div class="mb-3">
<label class="form-label">Status</label>
<select name="is_completed" id="" class="form-control">
<option value="1" @if($todo->is_completed==1) selected @endif>Complete</option>
<option value="0" @if($todo->is_completed==0) selected @endif>Not Complete</option>
</select>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
Notice in the above code, first we have form with title
and status
.
We are loading the title
using $todo->title
then we have status
with select
field in which have conditional rendering that if $todo->is_completed
is 1 then select the select
option Complete as selected
and I the $todo->is_completed
is 0 then select the select
option Not Complete.
Then we have submit button.
In form action you can see that we have linked to the update
method of TodoController
.
Note: That update method is actually
PUT
method but we are using method ofPOST
in this case.
The reason that HTML doesn’t have any way us to use thePUT
andDELETE
method.
Laravel solve this problem that if we want use thePUT
method we can passPOST
as the method and in body of form addmethod_field('PUT')
which will allow us to usePUT
method. How cool is that.
D) In update function, add logic for validation and updating the Todo
Now lets go to the update
function of TodoController
and add logic for validation and updating the Todo.
This is how the update
function will look like:
public function update(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'title' => 'required',
]);
if ($validator->fails())
{
return redirect()->route('todos.edit',['todo'=>$id])->withErrors($validator);
}
$todo=Todo::where('id',$id)->first();
$todo->title=$request->get('title');
$todo->is_completed=$request->get('is_completed');
$todo->save();
return redirect()->route('todos.index')->with('success', 'Updated Todo');
}
In the above code, first we validate the request using Laravel Validation
, that the title
is required. If the title
not set, it will redirect to edit
route otherwise the code will continue.
Then we are saving the title
and the selected is_completed
status using laravel save()
function and redirecting back to the index
function.
Now if click on the edit button, it will show something like this:
So if the title
is not present and you click on submit button it will show like this:
And if the title is present and you click on the submit button it will redirect back to index
the function which will load all todos with todos.blade.php
view.
Step 12: Lets write code for Delete Operation
In order to perform the delete operation:
A) We need to assign the Delete Button the destory
function of the TodoController
.
B) Add GET
method route that will call destory
function of TodoController
.
C) In Destory
function, add logic to Delete Todo.
A) Assign Delete Button Delete function
In this very first step, we will assign the Delete button to call the destory
function.
So we will change the Delete Button in todos.blade.php
.
<a href="{{route('todos.destory',['todo'=>$todo->id])}}" class="btn btn-danger">Delete</a>
In the above code, we are assigning the destroy
function and passing the todo id
which we want to delete.
B) Add GET method route that will call destory function of TodoController
The destroy
function is actually DELETE
method. Since we cannot call the DELETE
method using HTML.
Add the following code in routes/web.php
:
Route::get('todos/{todo}', [\App\Http\Controllers\TodoController::class,'destroy'])->name('todos.destory');
In the above code, we convert that DELETE
to be GET
method in case of destroy
function.
So for that purpose we had add new method GET
route for delete that will basically call the destroy
function.
C) In Destory function, add logic to Delete Todo
In this step, we will add logic to delete Todo in the destory
function.
Add the following code:
public function destroy($id)
{
Todo::where('id',$id)->delete();
return redirect()->route('todos.index')->with('success', 'Deleted Todo');
}
You can see that in the above code, that in the first line we passing id
of the todo Item we want to delete and then deleting it using laravel delete()
function.
Then we are redirecting to the index
function with message of Deleted Todo.
So if you click on Delete Button, it will show something like this:
Hurray! With that we have completed all 4 CRUD operations.
Full Code
1- Full Code of Route/web.php file
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::resource('todos', \App\Http\Controllers\TodoController::class);
Route::get('todos/{todo}', [\App\Http\Controllers\TodoController::class,'destroy'])->name('todos.destory');
2- Full Code for todos.blade.php file
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="row justify-content-center mt-5">
<div class="col-lg-6">
@if(session()->has('success'))
<div class="alert alert-success">
{{ session()->get('success') }}
</div>
@endif
@if ($errors->any())
@foreach ($errors->all() as $error)
<div class="alert alert-danger">
{{$error}}
</div>
@endforeach
@endif
</div>
</div>
<div class="text-center mt-5">
<h2>Add Todo</h2>
<form class="row g-3 justify-content-center" method="POST" action="{{route('todos.store')}}">
@csrf
<div class="col-6">
<input type="text" class="form-control" name="title" placeholder="Title">
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-3">Submit</button>
</div>
</form>
</div>
<div class="text-center">
<h2>All Todos</h2>
<div class="row justify-content-center">
<div class="col-lg-6">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Created at</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
@php $counter=1 @endphp
@foreach($todos as $todo)
<tr>
<th>{{$counter}}</th>
<td>{{$todo->title}}</td>
<td>{{$todo->created_at}}</td>
<td>
@if($todo->is_completed)
<div class="badge bg-success">Completed</div>
@else
<div class="badge bg-warning">Not Completed</div>
@endif
</td>
<td>
<a href="{{route('todos.edit',['todo'=>$todo->id])}}" class="btn btn-info">Edit</a>
<a href="{{route('todos.destory',['todo'=>$todo->id])}}" class="btn btn-danger">Delete</a>
</td>
</tr>
@php $counter++; @endphp
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>
3- Full Code for edit-todo.blade.php file
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="row justify-content-center mt-5">
<div class="col-lg-6">
@if(session()->has('success'))
<div class="alert alert-success">
{{ session()->get('success') }}
</div>
@endif
@if ($errors->any())
@foreach ($errors->all() as $error)
<div class="alert alert-danger">
{{$error}}
</div>
@endforeach
@endif
</div>
</div>
<div class="text-center mt-5">
<h2>Edit Todo</h2>
</div>
<form method="POST" action="{{route('todos.update',['todo'=>$todo->id])}}">
@csrf
{{ method_field('PUT') }}
<div class="row justify-content-center mt-5">
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Title</label>
<input type="text" class="form-control" name="title" placeholder="Title" value="{{$todo->title}}">
</div>
<div class="mb-3">
<label class="form-label">Status</label>
<select name="is_completed" id="" class="form-control">
<option value="1" @if($todo->is_completed==1) selected @endif>Complete</option>
<option value="0" @if($todo->is_completed==0) selected @endif>Not Complete</option>
</select>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>
4- Full Code for TodoController file
<?php
namespace App\Http\Controllers;
use App\Models\Todo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class TodoController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
$todos=Todo::all();
return view('todo',compact('todos'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
$validator = Validator::make($request->all(), [
'title' => 'required',
]);
if ($validator->fails())
{
return redirect()->route('todos.index')->withErrors($validator);
}
Todo::create([
'title'=>$request->get('title')
]);
return redirect()->route('todos.index')->with('success', 'Inserted');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
$todo=Todo::where('id',$id)->first();
return view('edit-todo',compact('todo'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'title' => 'required',
]);
if ($validator->fails())
{
return redirect()->route('todos.edit',['todo'=>$id])->withErrors($validator);
}
$todo=Todo::where('id',$id)->first();
$todo->title=$request->get('title');
$todo->is_completed=$request->get('is_completed');
$todo->save();
return redirect()->route('todos.index')->with('success', 'Updated Todo');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
Todo::where('id',$id)->delete();
return redirect()->route('todos.index')->with('success', 'Deleted Todo');
}
}
Conclusion
Hope in the above article, you have learned today how to do the CRUD (Create Read Update and Delete) Operation in laravel 9 using Bootstrap 5 for Todo App.
The above crash course has been created by keeping beginners in mind so every part of the above tutorial explained step by step.
Let me know if you have any questions in the comments, I will see you in the next one 🙂 See yaa.
Write a Reply or Comment