Setting up Laravel
A lot has changed in setting up Laravel since the release of the current version 8, you can get full details on how to install and set up Laravel here.
We are going to use the conventional way assuming you have composer installed already. We will create a todo-app with our Laravel installation, just run the following command:
composer create-project laravel/laravel todo-app
Next, change your directory to the current created directory:
Open your project with any code editor of your choice, I will be using Visual Studio Code.
Lastly, run the following command to serve your webpage.
Visit http://127.0.0.1:8000 in your browser to test your newly created Laravel project.
Cheers 🙂
Setting up Database
After installing Laravel, you almost do not need any additional set up except if you want to change timezones or other specific configurations, then you can review the config/app file to see the different configurations available.
But if you’re good with the defaults, let’s look at how to configure our database:
First, create a new database using any Database Client of your choice and note the login credentials.
Next, open the .env file (or create a new one if not exists), update the following information.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=DB NAME HERE
DB_USERNAME=DB USERNAME HERE
DB_PASSWORD=DB PASSWORD HERE
In our case, we will stick with mysql database.
Setting up the Schema
The next step is to set up your database migrations and configure your database Eloquent Relationships.
Run the following command in the same terminal, to create a database schema file for our Todo table.
php artisan make:migration create_todos_table --create=todos
That command will create a new migration file inside database/migrations/xxx_create_todos_table.php, open it and paste in the following codes.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTodosTable extends Migration
{
public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('desc')->nullable();
$table->integer('status')->default(0);
$table->integer('user_id');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('todos');
}
}
Lastly, before you migrate the database, note that you can set up Database Seeders to generate fake data for your database, or clone my repository since I have configured database seeders already.
Now, run the migration:
Set up User Authentication with Laravel Breeze
Initially, setting up authentication without the use of packages can be tedious because you will have to code everything from Registration, Login to Forgot Password logic.
But with the use of Laravel Breeze, the authentication process is made very easy and less time-consuming.
Let’s install and set up our authentication process with minutes:
composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev
With these few commands, your authentication process is set, navigate to http://127.0.0.1:8000/register or http://127.0.0.1:8000/login, if you see the following screenshots then everything is properly set up.

All Laravel Breeze configuration can be found at config/auth.php, then all the Authentication logic is found in app/Http/Controllers/Auth, and all the UI interface files can be found at resources/views/auth.
You can start studying the authentication process from there.
Creating Models
If you look at the App folder, you might see a Models folder if Laravel 8 and a User.php file inside it or you might see User.php file inside the App folder.
That is exactly what a Model is:
Just a file that contains methods and properties to interact with our Database Schema, inside the User.php, you will notice that it extends (inherit) the Model parent class that is where all the methods and properties to interact with our Database Schema is coming from.
We can use the pre-defined User model to retrieve or create a new user in our application by providing the data needed in the User schema at database/migrations/xxxx_create_users_xxxx.php file.
Let’s take a look:
To retrieve all the users in our database, we will simply do:
$users = User::all();
foreach($users as $user){
echo $user->name
}
To retrieve a particular user based on ID:
$user = User::find(1)
echo $user->name;
Create a new User (No need for SQL insert statement)
$user = new User;
$user->name = "Solomon Eseme";
$user->email = "[email protected]";
$user->password = "strongpassword";
$user->save();
By calling the save() method of the model instance, Laravel will either create a new User or update the existing User.
To delete a User from your Database, simply run:
$deletedUser = User::find(1)->delete();
Deleting a User is simply done by calling the delete method of the Model.
To retrieve Users with certain conditions, you can user the where method the Laravel Models
$users = User::where('email', '!=', '')->get();
foreach($users as $user){
echo $user->name
}
Again, that will retrieve all the users that have email addresses added.
Now that we have a glimpse of what Laravel Models are, let’s create our own Todo Model to interact with the Todo schema we create above.
Open your project terminal and run the following command.
php artisan make:model Todo
The command will generate a new Todo Model inside app folder or app/Models folder (Laravel 8).
Open the file and go through it to see if the content is familiar from the User’s model we explored earlier.
You don’t need to do anything, for now, let’s move on to creating controllers.
Creating Controllers
Again, controllers are like the middleman between requests (views) and models.
When a user sends a request to your backend either by clicking a button or submitting a form, the request passes through the routes to the controller and the controller calls out to your model to serve the request and returns a response back to the user (View).
With this flow in mind, let’s create our first controller to handle any request for the Todos:
Run the following command in your project terminal to create a new controller.
php artisan make:controller TodosController
There are naming conventions in the official documentation, but any name will do.
The command above will create a controller file inside app/Https/Controllers, open the TodosController file and look at the generated content.
CRUD Controller
Next, we are going to create a CRUD operation to interact with our Model and serve the users of our application (Views).
Add the following codes to the newly created controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TodosController extends Controller
{
public function index(Request $request)
{
}
public function show(Request $request, $id)
{
}
public function edit(Request $request)
{
}
public function update(Request $request)
{
}
public function create(Request $request)
{
}
public function store(Request $request)
{
}
public function delete(Request $request)
{
}
}
This is just a skeleton of how the controller will look like. Now, let’s fill in the content of each method.
A complete code for our controller will look like this:
<?php
namespace App\Http\Controllers;
use App\Models\Todo;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
class TodosController extends Controller
{
public function index(Request $request)
{
$todos = Todo::all();
return view('dashboard')->with(['todos' => $todos]);
}
public function byUserId(Request $request)
{
$todos = Todo::where('user_id', Auth::user()->id)->get();
return view('dashboard')->with(['todos' => $todos]);
}
public function show(Request $request, $id)
{
$todo = Todo::find($id);
return view('show')->with(['todo' => $todo]);
}
public function edit(Request $request, $id)
{
$todo = Todo::find($id);
return view('edit', ['todo' => $todo]);
}
public function update(Request $request, $id)
{
$todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first();
if ($todo) {
$todo->title = $request->title;
$todo->desc = $request->desc;
$todo->status = $request->status == 'on' ? 1 : 0;
if ($todo->save()) {
return view('show', ['todo' => $todo]);
}
return;
}
return;
}
public function create(Request $request)
{
return view('add');
}
public function store(Request $request)
{
$todo = new Todo;
$todo->title = $request->title;
$todo->desc = $request->desc;
$todo->user_id = Auth::user()->id;
if ($todo->save()) {
return view('show', ['todo' => $todo]);
}
return;
}
public function delete(Request $request, $id)
{
$todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first();
if ($todo) {
$todo->delete();
return view('index');
}
return;
}
}
As this is a beginner’s guide, there are lots we did not bother checking, like validations, clean code, errors, and others.
From the code above, you can see how we interact with our Todo model and serve the User’s request by calling the view method and passing on the HTML page we want the user to see.
For example, if a user clicks on our edit button, the request is sent to the edit method of the TodosController, then, the controller will find the particular Todo by ID (using the Todo model methods) and return back an Edit Form (HTML) filled with that particular Todo data to the user.
The Request object contains lots of Information about the current request the user is sending to our application but for now, we only used it to retrieve the data we need to create or update our Todo model.
To learn more about Requests, check here.
Creating Routes
Next, we are going to look at creating routes that map user’s requests to individual methods in any controller based on the user’s request.
When a user clicks on a button or submits a form, how does Laravel know which method to call or which controller to send the request to?
Well, everything is defined and mapped using a Routing System.
Laravel has an elegant routing system build in already:
Now, open the web.php file inside the routes folder and add the following codes:
Route::get('/login', function () {
return view('welcome');
});
Route::get('/todos/mine', [TodosController::class, 'byUserId'])->middleware(['auth'])->name('mine');
Route::get('/todos/{id}/edit', [TodosController::class, 'edit'])->middleware(['auth'])->name('edit-form');
Route::get('/todos/create', [TodosController::class, 'create'])->middleware(['auth'])->name('create-form');
Route::post('/todos/{id}/update', [TodosController::class, 'update'])->middleware(['auth'])->name('update');
Route::post('/todos/add', [TodosController::class, 'store'])->middleware(['auth'])->name('add');
Route::get('/todos/{id}', [TodosController::class, 'show'])->middleware(['auth'])->name('show');
Route::delete('/todos/:id', [TodosController::class, 'delete'])->middleware(['auth'])->name('delete');
Route::get('/dashboard', [TodosController::class, 'index'])->middleware(['auth'])->name('dashboard');
require __DIR__ . '/auth.php';
You can see that each method in our TodosController is mapped onto a specific URL (route) in the webpage.
You can get more information about Laravel Routing System.
Creating Views
Dashboard view
The Dashboard view is the dashboard when a user successfully registers and login, it will present a list of all the Todos in our application and can also be sorted by individual todos.
Create a new blade file inside resources/views/dashboard.blade.php and paste in the following codes.
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<x-button-link href="{{ route('create-form') }}">Add new todo</x-button-link>
</div>
</div>
</div>
</div>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="panel-bod">
<table class="table">
<thead>
<th>All Todos</th>
<th> </th>
<th>
<x-button-link href="{{ route('mine') }}">Show mine</x-button-link>
</th>
</thead>
<tbody class="max-w-full">
@foreach($todos as $todo)
<tr class="max-w-full">
<td class="pt-5 pb-5 pr-5">
<h1 class="sm:font-bold">{{ $todo->title }}</h1>
<p>{{ $todo->desc }}</p>
<p class="pt-2 text-gray-500"> Added By: {{ $todo->user->id == auth()->user()->id? 'You':$todo->user->name }}</p>
</td>
<td>
<div>
<x-button-link href="/todos/{{$todo->id}}" class="bg-green-500">View</x-button-link>
@if($todo->user_id == auth()->user()->id)
<x-button-link href="{{ route('edit-form', ['id'=>$todo->id]) }}" class="bg-yellow-500">Edit</x-button-link>
<x-button-link href="/todos/{{$todo->id}}/delete" class="bg-red-500">Delete</x-button-link>
@endif
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
Show view
The Show View displays only the information of a particular Todo when a user clicks to see more details.
Create a new blade file inside resources/views/show.blade.php and paste in the following codes.
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
You're logged in!
</div>
</div>
</div>
</div>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="panel-bod">
<table class="table">
<thead>
<th>Todo</th>
<th> </th>
</thead>
<tbody class="max-w-full">
<tr class="max-w-full">
<td class="pt-5 pb-5 pr-5">
<h1 class="sm:font-bold">{{ $todo->title }}</h1>
<p>{{ $todo->desc }}</p>
<div class="flex content-between">
<p class="pt-2 text-gray-500 pr-5"> Added By: {{ $todo->user->name }}</p>
<p class="pt-2 text-gray-500"> Status: {{ $todo->status == 1? "Done": "Pending"}}</p>
</div>
</td>
<td>
<div>
<x-button-link href="/todos/{{$todo->id}}" class="bg-green-500">View</x-button-link>
@if($todo->user_id == auth()->user()->id)
<x-button-link href="{{ route('edit-form', ['id'=>$todo->id]) }}" class="bg-yellow-500">Edit</x-button-link>
<x-button-link href="/todos/{{$todo->id}}/delete" class="bg-red-500">Delete</x-button-link>
@endif
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
Edit view
The Edit View contains a form to update a particular Todo when the owner of the Todo clicks on the edit button.
Create a new blade file inside resources/views/edit.blade.php and paste in the following codes.
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form class="max-w-full" method="post" action="{{route('update', ['id'=>$todo->id])}}">
@csrf
<x-label class="pt-5 pb-5 pr-5">
Title
<x-input name="title" placeholder="Enter title" class="p-3 border-gray-900" value="{{$todo->title}}"></x-input>
</x-label>
<x-label class="pt-5 pb-5 pr-5">
Description
<textarea name="desc">{{ $todo->desc }}</textarea>
</x-label>
<x-label class="pt-5 pb-5 pr-5">
Status
<input name="status" type="checkbox" {{$todo->status==1 ? 'checked': ''}}>Done
</ input>
</x-label>
<x-button>Submit</x-button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
Add view
The Add View contains a form to add/create a new particular Todo when a user clicks on the add button.
Create a new blade file inside resources/views/add.blade.php and paste in the following codes.
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form class="max-w-full" method="post" action="{{ route('add') }}">
@csrf
<x-label class="pt-5 pb-5 pr-5">
Title
<x-input required name="title" placeholder="Enter title" class="p-3 border-gray-900"></x-input>
</x-label>
<x-label class="pt-5 pb-5 pr-5">
Description
<textarea required name="desc"></textarea>
</x-label>
<x-button>Submit</x-button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
Preview.
If you get everything correctly, you should be presented with a dashboard like this:

Congratulations on making it this far!
When it comes to learning Laravel, I will personally and highly recommend these 3 courses. With it, I was able to learn and start building projects within a week.
Laravel 8 Beginner to Advance with Complete News Portal
PHP with Laravel for beginners – Become a Master in Laravel
Laravel 2019, the complete guide with real world projects
Take a break and subscribe to get access to our free Laravel tips that will improve your productivity.