A Beginner's Guide to Creating a Simple Task Manager from Start to Finish.
Laravel is an elegant and powerful PHP framework designed to make web development enjoyable. It provides a rich set of tools and conventions that streamline common web development tasks.
In this tutorial, we will build a complete **Task Manager** application that demonstrates the four fundamental **CRUD** operations: **C**reate, **R**ead, **U**pdate, and **D**elete tasks.
To create a web application where a user can view a list of tasks, add new tasks, edit existing ones, and delete them.
First, we'll use Composer to create a brand new Laravel project.
Open your terminal and run the following command:
composer create-project laravel/laravel task-manager
This will download Laravel and all its dependencies into a new folder called `task-manager`.
Navigate into your new project's directory:
cd task-manager
Now, run the initial migration command. This will automatically create the `database/database.sqlite` file and set up the default tables (like for users).
php artisan migrate
We need a `Task` model to represent a task in our application and a migration to create the `tasks` table in our database.
Laravel's command-line tool, **Artisan**, can create both for us with a single command:
php artisan make:model Task -m
The `-m` flag tells Artisan to also create a database migration file for the `Task` model.
Open the new migration file located at `database/migrations/...._create_tasks_table.php`. Let's add columns for a `title` and a `completed` status.
// ... inside the up() method
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->boolean('completed')->default(false);
$table->timestamps();
});
Now, apply this new migration to create the `tasks` table in your database:
php artisan migrate
Open the model file at `app/Models/Task.php`. We need to specify which fields are "fillable" to prevent mass-assignment vulnerabilities.
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['title', 'completed'];
}
A **Controller** handles the application logic. We'll create one to manage our tasks. Using the `--resource` flag will pre-fill the controller with methods for each CRUD action.
php artisan make:controller TaskController --resource
Now, open `app/Http/Controllers/TaskController.php` and fill in the logic.
namespace App\Http\Controllers;
use App\Models\Task;
use Illuminate\Http\Request;
class TaskController extends Controller
{
// Display a listing of the tasks.
public function index()
{
$tasks = Task::latest()->get();
return view('tasks.index', compact('tasks'));
}
// Show the form for creating a new task.
public function create()
{
return view('tasks.create');
}
// Store a newly created task in storage.
public function store(Request $request)
{
$request->validate(['title' => 'required|max:255']);
Task::create($request->all());
return redirect()->route('tasks.index')->with('success', 'Task created successfully.');
}
// Show the form for editing the specified task.
public function edit(Task $task)
{
return view('tasks.edit', compact('task'));
}
// Update the specified task in storage.
public function update(Request $request, Task $task)
{
$request->validate(['title' => 'required|max:255']);
$task->update($request->all());
return redirect()->route('tasks.index')->with('success', 'Task updated successfully.');
}
// Remove the specified task from storage.
public function destroy(Task $task)
{
$task->delete();
return redirect()->route('tasks.index')->with('success', 'Task deleted successfully.');
}
}
A **Route** connects a URL to a controller action. Instead of defining each CRUD route manually, Laravel provides a convenient "resource" route that does it all in one line.
Open `routes/web.php` and add the following code:
use App\Http\Controllers\TaskController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return redirect()->route('tasks.index');
});
Route::resource('tasks', TaskController::class);
This single `Route::resource` line creates all the necessary routes for viewing, creating, editing, and deleting tasks. It's incredibly efficient!
**Blade** is Laravel's powerful templating engine. We'll create a few files in the `resources/views/tasks` directory (you'll need to create the `tasks` folder).
Create a `layout.blade.php` file in `resources/views`. This will be our main site template.
<!DOCTYPE html>
<html>
<head>
<title>Task Manager</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
@yield('content')
</div>
</body>
</html>
This view will display all the tasks.
@extends('layout')
@section('content')
<h1>Task List</h1>
<a href="{{ route('tasks.create') }}" class="btn btn-primary mb-3">Add New Task</a>
@if ($message = Session::get('success'))
<div class="alert alert-success">{{ $message }}</div>
@endif
<table class="table table-bordered">
<tr>
<th>ID</th>
<th>Title</th>
<th width="280px">Action</th>
</tr>
@foreach ($tasks as $task)
<tr>
<td>{{ $task->id }}</td>
<td>{{ $task->title }}</td>
<td>
<form action="{{ route('tasks.destroy',$task->id) }}" method="POST">
<a class="btn btn-info" href="{{ route('tasks.edit',$task->id) }}">Edit</a>
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
@endforeach
</table>
@endsection
@extends('layout')
@section('content')
<h1>Add New Task</h1>
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('tasks.store') }}" method="POST">
@csrf
<div class="mb-3">
<label for="title" class="form-label">Title:</label>
<input type="text" name="title" class="form-control" placeholder="Title">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<a class="btn btn-secondary" href="{{ route('tasks.index') }}"> Back</a>
</form>
@endsection
@extends('layout')
@section('content')
<h1>Edit Task</h1>
@if ($errors->any())
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('tasks.update',$task->id) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
<label for="title" class="form-label">Title:</label>
<input type="text" name="title" value="{{ $task->title }}" class="form-control" placeholder="Title">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<a class="btn btn-secondary" href="{{ route('tasks.index') }}"> Back</a>
</form>
@endsection
Everything is now ready! Go to your terminal (in the `task-manager` directory) and start the Laravel development server:
php artisan serve
Now, open your web browser and navigate to the address provided (usually http://127.0.0.1:8000).
You should see your task list application. You can now add, edit, and delete tasks!
You have successfully created a complete web application from scratch using Laravel. This project covers the essential workflow of modern web development.
You learned how to:
This is a solid foundation for building more complex and feature-rich a