Building a Basic CRUD Application: Walking through the process of creating a simple CRUD (Create, Read, Update, Delete) application using Laravel

Building a Basic CRUD Application: Walking through the process of creating a simple CRUD (Create, Read, Update, Delete) application using Laravel

Introduction

In this tutorial, we will walk you through the process of building a basic CRUD application using Laravel, a popular PHP framework. We will be creating a simple Task Manager application where users can create, read, update, and delete tasks. To make our application visually appealing, we will utilize the Bootstrap framework for the frontend.

Prerequisites

  • PHP installed on your local machine

  • Composer installed on your local machine

  • Laravel installed on your local machine

  • Basic understanding of PHP and Laravel

Laravel CRUD Steps

Step 1:

Create a new Laravel project First, let's create a new Laravel project using the Laravel installer. Open your terminal and run the following command:

composer create-project --prefer-dist laravel/laravel task-manager

This will create a new Laravel project named "task-manager".

Step 2:

Set up the database Next, let's configure the database for our application. Open the .env file in the root directory of your project and update the following lines with your database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_password

Save the changes and create a new database in your MySQL server with the name specified in the .env file.

Note: In case you don't have the .env file simply copy the ..env.example and rename it to .env

Step 3:

Create the Task model and migration Now, let's create a model and migration for our Task. In your terminal, navigate to the root directory of your project and run the following command:

php artisan make:model Task -m

This will generate a new model file Task.php and a migration file. Open the migration file located in the database/migrations directory and update it with the following code:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

Save the changes and run the migration command in your terminal:

php artisan migrate

This will create the tasks table in your database.

Step 4:

We need to specify the fillable attributes in the Task model to allow mass assignment. Open Task model in app/Models/Task.php and update it with:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'description'];
}

Make sure to add the $fillable array with the desired attributes that can be mass assigned. In this case, we have title and description attributes.

Save the changes to the Task.php file.

Step 5:

Create a seeder To populate our tasks table with some sample data, let's create a seeder. Run the following command in your terminal:

php artisan make:seeder TaskSeeder

This will generate a new seeder file TaskSeeder.php in the database/seeders directory. Open the TaskSeeder.php file and update it with the following code:

<?php

namespace Database\Seeders;

use App\Models\Task;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class TaskSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('tasks')->insert([
            'title' => 'Blog Post',
            'description' => 'Write blog post on laravel crud',
            'created_at' => Carbon::now(),
        ]);
    }
}

Save the changes.

Let's register our TaskSeeder, open the Database\Seeder and modify with the code below.

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(TaskSeeder::class);
    }
}

Step 6:

Run the seeder Now, let's run the seeder to populate our tasks table with sample data. In your terminal,

run the following command:

php artisan db:seed --class=TaskSeeder

This will execute the run() method within the TaskSeeder class and create 10 sample tasks in the tasks table.

Step 7:

Set up routes and controller Let's define the routes and controller methods for our CRUD operations. Open the routes/web.php file and update it with the following code:

<?php

use App\Http\Controllers\TaskController;
use Illuminate\Support\Facades\Route;

Route::get('/', [TaskController::class, 'index'])->name('tasks.index');
Route::get('/tasks/create', [TaskController::class, 'create'])->name('tasks.create');
Route::post('/tasks', [TaskController::class, 'store'])->name('tasks.store');
Route::get('/tasks/{task}', [TaskController::class, 'show'])->name('tasks.show');
Route::get('/tasks/{task}/edit', [TaskController::class, 'edit'])->name('tasks.edit');
Route::put('/tasks/{task}', [TaskController::class, 'update'])->name('tasks.update');
Route::delete('/tasks/{task}', [TaskController::class, 'destroy'])->name('tasks.destroy');

Save the changes.

We can also use resource routing instead of defining each route ourselves. To do that we replace the above code with this:

use App\Http\Controllers\TaskController;

Route::resource('tasks', TaskController::class);

Next, we create a new controller file by running the following command in your terminal:

php artisan make:controller TaskController --resource

This will generate a new controller file TaskController.php with resourceful methods for CRUD operations.

Note: We can use the below command to create the model, migration and controller with resources at once using this command:

php artisan make:mode -mcr

Now that we have created our controller let open the TaskController.php file located in the app/Http/Controllers directory and update it with the following code:

<?php

namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\Request;

class TaskController extends Controller
{
    // This display all task
    public function index()
    {
        $tasks = Task::latest()->get();
        return view('pages.tasks.index', compact('tasks'));
    }

    // Return the form for creating task
    public function create()
    {
        return view('pages.tasks.create');
    }

    // Store request from task form
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'description' => 'nullable',
        ]);

        Task::create($request->all());

        return redirect('/')
            ->with('success', 'Task created successfully!');
    }

    // Show single task
    public function show(Task $task)
    {
        return view('pages.tasks.show', compact('task'));
    }


    // Display edit  task form
    public function edit(Task $task)
    {
        return view('pages.tasks.edit', compact('task'));
    }

    // Store request from task update form
    public function update(Request $request, Task $task)
    {
        $request->validate([
            'title' => 'required',
            'description' => 'nullable',
        ]);

        $task->update($request->all());

        return redirect('/')
            ->with('success', 'Task updated successfully!');
    }

    // Delete a single task
    public function destroy(Task $task)
    {
        $task->delete();

        return redirect('/')
            ->with('success', 'Task deleted successfully!.');;
    }
}

Save the changes.

Step 8:

Create the views Next, let's create the views for our Task Manager application. Create a new directory named pages inside the resources/views and another directory called tasks inside the resources/views directory. Inside the tasks directory, create the following blade templates:

  • index.blade.php (listing all tasks)

  • create.blade.php (form for creating a new task)

  • show.blade.php (displaying a single task)

  • edit.blade.php (form for editing a task)

How, let's modify each of the blade templates. Open each blade template and update accordingly:

  • index.blade.php

      @extends('layouts.app')
    
      @section('content')
          <h1>Task Manager</h1>
          <a href="{{ route('tasks.create') }}" class="btn btn-primary mb-3">Create Task</a>
          <table class="table table-responsive table-bordered">
              <thead>
                  <tr>
                      <th class="col-md-8">Title</th>
                      <th class="col-md-4">Actions</th>
                  </tr>
              </thead>
              <tbody>
                  @forelse ($tasks as $task)
                      <tr>
                          <td class="col-md-8">{{ $task->title }}</td>
                          <td class="col-md-4">
                              <a href="{{ route('tasks.show', $task->id) }}" class="btn btn-info btn-sm">View</a>
                              <a href="{{ route('tasks.edit', $task->id) }}" class="btn btn-primary btn-sm">Edit</a>
                              <form action="{{ route('tasks.destroy', $task->id) }}" method="POST" class="d-inline">
                                  @csrf
                                  @method('DELETE')
                                  <button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this task?')">Delete</button>
                              </form>
                          </td>
                      </tr>
                  @empty
                      <tr>
                          <td colspan="3">No tasks found.</td>
                      </tr>
                  @endforelse
              </tbody>
          </table>
      @endsection
    
  • create.blade.php

      @extends('layouts.app')
    
      @section('content')
          <h1>Create Task</h1>
          <form action="{{ route('tasks.store') }}" method="POST">
              @csrf
              <div class="form-group">
                  <label for="title">Title</label>
                  <input type="text" name="title" id="title" class="form-control" required>
              </div>
              <div class="form-group">
                  <label for="description">Description</label>
                  <textarea name="description" id="description" class="form-control"></textarea>
              </div>
              <button type="submit" class="btn btn-primary">Create</button>
          </form>
      @endsection
    
  • show.blade.php

      @extends('layouts.app')
    
      @section('content')
          <h1>{{ $task->title }}</h1>
          <p>{{ $task->description }}</p>
          <a href="{{ route('tasks.index') }}" class="btn btn-secondary">Back</a>
      @endsection
    
  • edit.blade.php

      @extends('layouts.app')
    
      @section('content')
          <h1>Edit Task</h1>
          <form action="{{ route('tasks.update', $task->id) }}" method="POST">
              @csrf
              @method('PUT')
              <div class="form-group">
                  <label for="title">Title</label>
                  <input type="text" name="title" id="title" class="form-control" value="{{ $task->title }}" required>
              </div>
              <div class="form-group">
                  <label for="description">Description</label>
                  <textarea name="description" id="description" class="form-control">{{ $task->description }}</textarea>
              </div>
              <button type="submit" class="btn btn-primary">Update</button>
          </form>
      @endsection
    

Save the changes.

Step 9:

Include Bootstrap Styles To make our application visually appealing, let's include the Bootstrap styles. Open

the app.blade.php file located in the resources/views/layouts directory and update it with the following code:

<!DOCTYPE html>
<html>

<head>
    <title>Task Manager</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <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>

    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>

<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="{{ route('tasks.index') }}">Task Manager</a>
    </nav>
    <div class="container mt-4">
        <div class="notifications">
            {{-- Notification Alert --}}

            @if (session('success'))
                <div class="alert alert-success alert-dismissible fade show" role="alert" id="success-alert">
                    {{ session('success') }}
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            @elseif (session('error'))
                <div class="alert alert-danger alert-dismissible fade show" role="alert" id="success-alert">
                    {{ session('error') }}
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            @endif
        </div>

        @yield('content')
    </div>
</body>

</html>

Save the changes.

Step 10:

Test the application That's it! You've successfully built a basic CRUD application using Laravel and Bootstrap. To test the application, run the following command in your terminal:

php artisan serve

Open your browser and navigate to http://localhost:8000. You should see the Task Manager application, where you can create, read, update, and delete tasks.

You can get the full source code for this project on my GitHub

Conclusion

In this episode, we walked through the process of building a basic CRUD application using Laravel and Bootstrap. We created a Task Manager application where users can perform CRUD operations on tasks. Laravel's routing, controllers, models, and views made it easy to implement the desired functionality. Bootstrap's styles helped us create a visually appealing interface. Feel free to explore further and enhance the application with additional features based on your requirements.

That's it for this episode! In our next installment, we'll be discussing "Working with Eloquent ORM: Understanding Laravel's powerful Object-Relational Mapping (ORM) tool, Eloquent, and using it for database querying and relationships."

Remember, Laravel's documentation and vibrant community are valuable resources for further exploration.

Note: This blog post provides an overview of the core concepts of Laravel. Each concept deserves more in-depth exploration, and it's recommended to refer to the official Laravel documentation for comprehensive understanding.

If you found this series helpful and want to support our series, there are a few things you can do:

Share the knowledge: Spread the word about this tutorial series to your friends, colleagues, or anyone who might be interested in learning Laravel. The more people we can reach, the more we can help aspiring developers.

Engage with us: Leave comments on our blog posts or YouTube videos, asking questions or providing feedback. Your engagement helps us understand your needs better and deliver content that addresses your concerns.

Donate: If you find value in our tutorials and would like to contribute financially, you can consider making a donation. Your support allows me to continue producing quality content and improving the learning experience for our audience.

Subscribe and follow: Subscribe to our blog or YouTube channel I plan on also doing video content soon. Also follow me on social media to stay updated with the latest episodes, tutorials, and announcements. By staying connected, you'll never miss an opportunity to enhance your Laravel skills.

Thank you for being a part of my Laravel series. Your support and engagement mean the world to me. Together, let's make the journey of learning Laravel an exciting and fulfilling experience. See you in our next episode.

Happy coding!

Laravel Docs: laravel.com

Laravel Daily: laraveldaily.com

Laracast: laracasts.com