A Laravel 8 CRUD Example Tutorial for newcomers

8 months ago

The well-known PHP framework Laravel, with its clean syntax and potent capabilities, has transformed web development. CRUD operations (Create, Read, Update, Delete) are one of its fundamental features. In this blog article, I'll discuss how to do CRUD operations in Laravel.

Create a crude operation app in Laravel 8 by following these steps:

1. Create Laravel Project
2. Database Setup
3. Create a Model, Migration and Controller
4. Define Database Schema in Migration File
5. Run the Migration
6. Set the fillable property in Model
7. Define Routes
8. Create Views for CRUD App
9. Implement CRUD Operations
10. Run the Application

Step 1: Create Laravel Project

Install Laravel first in the local development environment. The PHP package management Composer can be used to start a fresh Laravel project:

composer create-project --prefer-dist laravel/laravel:^8.0 laravel-crud


Step 2: Database Setup

In the.env file, set up your database connection. Numerous databases, including MySQL, PostgreSQL, SQLite, and others, are supported by Laravel. Set your database login information, which should include DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, and DB_PASSWORD.
In this, we will set up a MySQL database. 

In .env file

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_crud
DB_USERNAME=root
DB_PASSWORD=

I don't have a password for this database, which has the name "laravel_crud" and the username "root".

Step 3: Create a Model, Migration File and Controller

Model: Describes the logic and data structure for working with a particular database table. Models are used to define relationships between data entities and for database operations.

Migration File: A migration file is a script that specifies and controls modifications to the database structure. It offers code-based database table and column creation or modification for developers, ensuring consistency across various contexts. Applying these migrations is simple with Laravel's Artisan command-line tool, keeping the database schema consistent with the application's coding.

Controller: Controller processes input, engages with models, and returns replies in order to handle HTTP requests. Between routes and views, controllers act as a bridge, enabling the logic of the program and user interactions.

In Laravel, you can use a single Artisan command to generate a model, its associated migration, and a controller all at once. The order of the commands is as follows:

php artisan make:model Student -mcr


Step 4: Define Database Schema in Migration File

To define the schema for the "persons" table, edit the produced migration file (2023_08_19_055230_create_people_table.php, for example). Inside the up method, include the columns you want for your "Student" resource:

(Note: You can find the above mentioned migration file in database/migrations directory)

public function up()
{
    Schema::create('students', function (Blueprint $table) {
        $table->id();
        $table->string('full_name');
        $table->string('address');
        $table->integer('age');
        $table->string('phone');
        $table->string('email')->unique();
        $table->timestamps();
    });
}


Step 5: Run the Migration

Run the migration to create the "students" table in your database:

php artisan migrate


Step 6: Set the fillable property in Model

The fillable property in Laravel is used to determine which model attributes can be mass-assigned. When generating or updating records, it's usual practice to use mass assignment, which allows you to set numerous attributes of a model using an array.

class Student extends Model
{
    use HasFactory;
    protected $fillable = ['full_name', 'address', 'age', 'phone', 'email'];
}

(Note: Person model is in App/Models directory in laravel 9)

Step 7: Define Routes

Define the routes for your "Person" CRUD operations in the routes/web.php file:

use App\Http\Controllers\StudentController;
Route::resource('student', StudentController::class);

 

Step 8: Create Views for CRUD App

Under the resources/views directory, you must create a view file. I'll create the view files "index.blade.php," "create.blade.php," and "edit.blade.php" under the resources/views/student directory for this CRUD application.

index.blade.php

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <title> Student </title>
</head>

<body>
    <div class="container">
        <h1 class="text-center"> Student List </h1>
        <a href="{{ route('student.create') }}" class="btn btn-primary mb-2"> Add New </a>

        {{-- To display success message --}}
        @if(session('success'))
            <div class="alert alert-success">
                {{ session('success') }}
            </div>
        @endif

        <table class="table">
            <thead>
                <tr>
                    <th scope="col"> S.N </th>
                    <th scope="col"> Full Name </th>
                    <th scope="col"> Age </th>
                    <th scope="col"> Address </th>
                    <th scope="col"> Phone </th>
                    <th scope="col"> Email </th>
                    <th scope="col"> Action </th>
                </tr>
            </thead>
            <tbody>
                @foreach ($students as $student)
                    <tr>
                        <th scope="row"> {{ $loop->iteration }} </th>
                        <td> {{ $student->full_name }} </td>
                        <td> {{ $student->age }} </td>
                        <td> {{ $student->address }} </td>
                        <td> {{ $student->phone }} </td>
                        <td> {{ $student->email }} </td>
                        <td>
                            <form action="{{ route('student.destroy',$student->id) }}" method="POST">
                                <a href="{{ route('student.edit', $student->id) }}" class="btn btn-sm btn-warning"> Edit </a>
                                @csrf
                                @method('DELETE')
                                <button type="submit" class="btn btn-sm btn-danger">Delete</button>
                            </form>
                        </td>
                    </tr>
                @endforeach
            </tbody>
        </table>
    </div>


    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous">
    </script>
</body>
</html>

 

create.blade.php

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <title> Add  New Student </title>
</head>

<body>
    <div class="container">
    <h1 class="text-center"> Add New Student </h1>

        <form method="POST" action="{{ route('student.store') }}">
            @csrf

            <!-- Full Name -->
            <div class="form-group">
                <label for="full_name">Full Name</label>
                <input type="text" class="form-control" id="full_name" name="full_name"
                    value="{{ old('full_name') }}" required>
            </div>

            <!-- Address -->
            <div class="form-group">
                <label for="address">Address</label>
                <input type="text" class="form-control" id="address" name="address" value="{{ old('address') }}"
                    required>
            </div>

            <!-- Age -->
            <div class="form-group">
                <label for="age">Age</label>
                <input type="number" class="form-control" id="age" name="age" value="{{ old('age') }}"
                    required>
            </div>

            <!-- Phone -->
            <div class="form-group">
                <label for="phone">Phone</label>
                <input type="text" class="form-control" id="phone" name="phone" value="{{ old('phone') }}"
                    required>
            </div>

            <!-- Email -->
            <div class="form-group">
                <label for="email">Email</label>
                <input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}"
                    required>
            </div>

            <!-- Submit Button -->
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous">
    </script>
</body>
</html>

 

edit.blade.php

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <title> Edit Student </title>
</head>

<body>
    <div class="container">
        <h1 class="text-center"> Edit Student </h1>

        {{-- To display error message --}}
        @if ($errors->any())
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif

        <form method="POST" action="{{ route('student.update', $student->id) }}">
            @csrf
            @method('PUT')

            <!-- Full Name -->
            <div class="form-group">
                <label for="full_name">Full Name</label>
                <input type="text" class="form-control" id="full_name" name="full_name"
                    value="{{ $student->full_name }}" required>
            </div>

            <!-- Address -->
            <div class="form-group">
                <label for="address">Address</label>
                <input type="text" class="form-control" id="address" name="address" value="{{ $student->address }}"
                    required>
            </div>

            <!-- Age -->
            <div class="form-group">
                <label for="age">Age</label>
                <input type="number" class="form-control" id="age" name="age" value="{{ $student->age }}"
                    required>
            </div>

            <!-- Phone -->
            <div class="form-group">
                <label for="phone">Phone</label>
                <input type="text" class="form-control" id="phone" name="phone" value="{{ $student->phone }}"
                    required>
            </div>

            <!-- Email -->
            <div class="form-group">
                <label for="email">Email</label>
                <input type="email" class="form-control" id="email" name="email" value="{{ $student->email }}"
                    required>
            </div>

            <!-- Submit Button -->
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous">
    </script>
</body>
</html>


Step 9: Implement CRUD Operations

Write methods for create, read, update, and delete actions utilizing your model to accomplish the CRUD activities in your App\Http\Controllers\StudentController;.

<?php

namespace App\Http\Controllers;

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

class StudentController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $students = Student::latest('created_at')->get();
        return view('student.index', ['students'=>$students]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('student.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validate = $request->validate([
            'full_name' => 'required',
            'email' => 'required|email',
            'phone' => 'required|max:13',
        ]);

        $student = Student::create([
            'full_name' => $validate['full_name'],
            'email' => $validate['email'],
            'phone' => $validate['phone'],
            'age' => $request->age,
            'address' => $request->address,
        ]);

        return redirect()->route('student.index')
                         ->with('success', 'Student added successfully.');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Student  $student
     * @return \Illuminate\Http\Response
     */
    public function show(Student $student)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Student  $student
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $student = Student::find($id);
        return view('student.edit', ['student'=>$student]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Student  $student
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $student = Student::find($id);
        $validate = $request->validate([
            'full_name' => 'required',
            'email' => 'required|email',
            'phone' => 'required|max:13',
        ]);

        $student->update([
            'full_name' => $validate['full_name'],
            'email' => $validate['email'],
            'phone' => $validate['phone'],
            'age' => $request->age,
            'address' => $request->address,
        ]);

        return redirect()->route('student.index')
                         ->with('success', 'Student updated successfully.');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Student  $student
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $student = Student::find($id);
        $student->delete();
        return redirect()->route('student.index')
                         ->with('success', 'Student deleted successfully.');
    }
}

 

Step 10: Run the Application

Run the application by following artisan command. 

php artisan serve

Your application will be run in 127.0.0.1:8000.

Finally, open the web browser and hit the following URL in address bar.

http://127.0.0.1:8000/student

You can now carry out CRUD activities in your own Laravel application that you have built. Thank You...

  950