Laravel 7 CRUD Tutorial with image class

By CodersDrive
11-Jun-2020
Laravel
Php

With this CRUD tutorial you will learn basics required to create any laravel application like Creating, Updating and Deleting a record with MySQL database. Please follow every step and do along for better understanding.

To do this practical on your machine you should have installed and configured PHP, Apache/Nginx etc server, Composer. If not done please follow the below articles.

Now Lets see the step by step procedure of our example.

Example: CRUD turorial with Student Profile
Step-1 Install Laravel Using Composer

At first download the Laravel installer using composer as per command shown below and install it globally on your machine.

composer global require laravel/installer
Step-2 Create a new laravel application

You can create new laravel application using either of the commands shown below

laravel new new_project_name_along_with_path
(or)
composer create-project laravel/laravel new_project_name_along_with_path

In our example we create new laravel project using "composer". Before creation go to the location where the project is to be created and then use the following command.

composer create-project laravel/laravel crud_example

Now a new laravel project will be created under folder name "crud_example" and downloads the required files and dependencies. Once the successful message is displayed you are ready to go and start developing new application.

We can see the created project index page using url "http://localhost/crud_example/public". This can be seen, if you created your project under installed servers document root path only.

If server(Apache/Nginx etc..) is not installed then also you can work on it and develop application using "Local Development Server" offered by Laravel itself for development using the following command

php artisan serve

Now you can see the project in your browser using url "http://localhost:8000"

Step-3 Bootstrap Scaffolding

Laravel offers Bootstrap scaffolding as frontend CSS framework. To scaffold our project with Bootsrap framework use the following commands.

composer require laravel/ui

This command will downloads the laravel/ui package to our application. Now scaffold this downloaded UI to our project using following command

php artisan ui bootstrap

Next install our project front end Javascript dependencies using NPM(Node Package Manager)

npm install

Once this installation is finished run the following command, this will create the required app.css file at public/css and app.js file at public/js.

npm run dev

These are the files that have the bootstrap framework scaffolding for your project.

Step-4 Setup .env file

Rename the .env.example to .env if not exist. Now run the following command to generate APP_KEY. This step is not required if APP_KEY value is already present in .env file. Also set the APP_NAME field with your desired Project name.

php artisan key:generate

Now configure the MySQL database access fileds in .env file with proper details as shown below.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=root
DB_PASSWORD=password
Step-5 Create Model and Migration

Create a Model Student along with migration (-m) using below command.

php artisan make:model Student -m

This will create Student.php model class under app/ and a migration file 2020_mm_dd_XXXX_create_students_table.php is created at database/migrations/. Edit this file and make modifications as per the code shown below.

<?php

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

class CreateStudentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return  void
     */
    public function up()
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id();
            $table->string('first_name');
            $table->string('middle_name')->nullable();
            $table->string('last_name');
            $table->date('dob');
            $table->string('place')->nullable();
            $table->string('email');
            $table->string('contact');
            $table->string('profile_pic')->nullable();
            $table->string('qualification');
            $table->timestamps();
        });
    }

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

In the above migration file we are adding the required columns with proper datatypes and nullable fields which we use to create a table in MySQL database. Now run the below command to create a studentstable in the MySQL database.

php artisan migrate

Once the migration is completed, you can verify it by logging into your MySQL DB.

Step-6 Create Routes

Now we will create all the routes that are required for this example. Open the file web.php under routes/ and append the following code to it.

Route::get('/show-students', 'StudentController@show');
Route::get('/add-student', function(){return view('add-student');});
Route::post('/upload-pp', 'StudentController@upload_pp');
Route::post('/save-student', 'StudentController@store');
Route::get('/edit-student/{id}', 'StudentController@edit');
Route::post('/update-student', 'StudentController@update');
Route::get('/delete-student/{id}', 'StudentController@delete');
Step-7 Create Controller

We will use these routes in our application at different points. StudentController is the Controller which we create using the below command.

php artisan make:controller StudentController

StudentController is created at app/Http/Controllers. In Laravel framework any operations with database are done at Controller through Model class.

Now edit the StudentController.php file and add the below code to it.

<?php

namespace App\Http\Controllers;

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

class StudentController extends Controller
{
    public function show()
    {
        $students = Student::OrderBy('first_name')->get();
        return view('show-students', compact('students'));
    }

    public function upload_pp()
    {
        if($_FILES["file"]["name"] != '')
            {
                $test = explode('.', $_FILES["file"]["name"]);
                $ext = end($test);
                $name = date_format(now(),'YmdHis').'-'.rand(100, 999) . '.' . $ext;
                if (!file_exists('storage/images')) {
                    mkdir('storage/images', 0777, true);
                }
                $location = 'storage/images/'.$name; 
               
                if($ext == 'jpg' || $ext == 'jpeg' || $ext == 'png')
                {
                    move_uploaded_file($_FILES["file"]["tmp_name"], $location);
                    $pp_orientation = Image::make(public_path($location))->exif("Orientation");
                            if($pp_orientation == 6 || $pp_orientation == 8)
                            {
                                $pp_resize = Image::make(public_path($location))->orientate()->resize('150','250');
                            }
                            else
                            {
                                $pp_resize = Image::make(public_path($location))->resize('150','250');
                            }
                            $pp_resize->save();
                    
                    echo '<img src="'.url($location).'" style="height:180px;width:120px;" class="img-thumbnail" /><br><h6>Image successfully uploaded!</h6><input type="text" name="thumbnail" value="'.$location.'" hidden>';
                    
                } else
                {
                    echo '<h4 class="text-danger">Invalid file type, try again by refreshing.</h4>';
                }
                
                
            }
    }

    public function store()
    {
        $data = request()->validate([
            'first_name' => 'required|string|min:3',
            'middle_name' => 'sometimes',
            'last_name' => 'required|string',
            'dob' => 'required|date',
            'qualification' => 'required|string',
            'place' => 'sometimes',
            'email' => 'required|email|unique:students',
            'contact' => 'required|numeric|digits_between:10,10',
        ]);

        $student = Student::create($data);

        if(isset($_POST['thumbnail']))
        {
            $student->update([
                'profile_pic' => $_POST['thumbnail'],
            ]);
        }

        return redirect('/show-students');
        
    }

    public function edit($id)
    {

        $a = Student::where('id',$id)->first();
        return view('edit-student', compact('a'));
    }

    public function update()
    {
        
        $data = request()->validate([
            'first_name' => 'required|string|min:3',
            'middle_name' => 'sometimes',
            'last_name' => 'required|string',
            'dob' => 'required|date',
            'qualification' => 'required|string',
            'place' => 'sometimes',
            'email' => 'required|email',
            'contact' => 'required|numeric|digits_between:10,10',
        ]);

        Student::where('id',$_POST['id'])->update($data);
        if(isset($_POST['thumbnail']))
        {
            //If profile pic is changed we will delete the old profile pic before updating the new one
            if(is_file(public_path($_POST['profile_pic'])))
                    {
                    unlink(public_path($_POST['profile_pic']));
                    }
            Student::where('id',$_POST['id'])->update([
                'profile_pic' => $_POST['thumbnail'],
            ]);
        }
        return redirect('/show-students');
    }

    public function delete($id)
    {
        $prof_pic = Student::where('id',$id)->first();
        if($prof_pic->profile_pic != Null)
        {
            if(is_file(public_path($prof_pic->profile_pic)))
                    {
                    unlink(public_path($prof_pic->profile_pic));
                    }
        } //Before deleting student profile we will delete his profile pic also.
        Student::where('id',$id)->delete();
        return redirect('/show-students');
    }
}
Step-8 Create Add Record Form

Create a form add-student.blade.php at resources/views/. Add the following code to this form.

@extends('layouts.app')
@section('content')
<div class="container">
<h2 class="text-center">Add Student</h2>
<form method="post" action="/save-student">
    <div class="row">
        <div class="col">
        <label for="first_name">First Name *:</label>
        <input type="text" class="form-control @error('first_name') is-invalid @enderror" name="first_name" value="{{old('first_name')}}" required>
                            @error('first_name')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                        </span>
                            @enderror 
        </div>
        <div class="col">
        <label for="middle_name">Middle Name:</label>
        <input type="text" class="form-control" name="middle_name" value="{{old('middle_name')}}">
        </div>
        <div class="col">
        <label for="last_name">Last Name *:</label>
        <input type="text" class="form-control @error('last_name') is-invalid @enderror" name="last_name" value="{{old('last_name')}}" required>
                            @error('last_name')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                        </span>
                            @enderror
        </div>
    </div>
    <div class="row mt-1">
        <div class="col">
        <label for="dob">Date Of Birth *:</label>
        <input type="date" class="form-control @error('dob') is-invalid @enderror" name="dob" value="{{old('dob')}}" required>
                            @error('dob')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                        </span>
                            @enderror
        </div>
        <div class="col">
        <label for="qualification">Qualification *:</label>
        <input type="text" class="form-control @error('qualification') is-invalid @enderror" name="qualification" value="{{old('qualification')}}" required>
                            @error('qualification')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                        </span>
                            @enderror
        </div>
        <div class="col">
        <label for="place">Place:</label>
        <input type="text" class="form-control" name="place" value="{{old('place')}}">
        </div>
    </div>
    <div class="row mt-1">
        <div class="col">
        <label for="profile_pic">Select image to upload:</label>
                <div class="custom-file mb-3">
                        
                            <input type="file" accept="image/*" class="custom-file-input" name="profile_pic" id="profile_pic">
                        
                            <label class="custom-file-label" for="customFile1">Upload Profile Pic</label>
                            
                          
                        </div>
        <label for="email">Email *:</label>
        <input type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{old('email')}}" required>
                            @error('email')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                        </span>
                            @enderror
        <label for="contact">Mobile No *:</label>
        <input type="number" class="form-control @error('contact') is-invalid @enderror" name="contact" value="{{old('contact')}}" required>
                            @error('contact')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                        </span>
                            @enderror
        </div>
        <div class="col text-center">
        
        <h5 class="text-danger"><small><b>  {{ $errors->first('profile_pic') }} </b></small></h5>
        <span id="uploaded_pp"></span>
        </div>

    </div>
    <button class="btn btn-primary btn-sm float float-right" type="submit">Add Student</button>
@csrf
</form>
</div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>

  

    $(document).ready( function() {
        
       

        $(document).on('change', '#profile_pic', function(){
           
        var name = document.getElementById("profile_pic").files[0].name;
        var form_data = new FormData();
        var ext = name.split('.').pop().toLowerCase();
        if(jQuery.inArray(ext, ['png','jpg','jpeg']) == -1) 
        {
        alert("Invalid File Format (Only images allowed)");
        }
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("profile_pic").files[0]);
        var f = document.getElementById("profile_pic").files[0];
        var fsize = f.size||f.fileSize;
        if(fsize > 2000000)
        {
        alert("File Size is very big (Allowed size is Max 2MB)");
        }
        else
        {
            event.preventDefault();
            
        form_data.append("file", document.getElementById('profile_pic').files[0]);

        $.ajax({
            url:"/upload-pp",
            method:"POST",
            data: form_data,
            contentType: false,
            cache: false,
            processData: false,
            beforeSend:function(){
            $('#uploaded_pp').html("<label class='text-dark'>Profile Pic Uploading...(Fill other fields)</label>");
            },   
            
            success:function(data)
            {
            $('#uploaded_pp').html(data);
            },
            resetForm: true
        });
        }
        });

        $.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    }
                    });

	});
</script>
@endsection

Now we have created a form to add a student record. We can access this page using url "http://localhost:8000/add-student". Please refer to the Route (/add-student) we have added earlier. You can also click here to see the demo of this page.

Here we have created a form to enter the student details, students profile pic also can be uploaded using AJAX. Route "/upload-pp" is used to upload the porfile pic of student using AJAX. When profile pic is uploaded upload_pp() function at StudentController.php is called and image is uploaded. Also we are using Image Class to check for orientation to be portrait and resize the image.

Route "/save-student" is used to post the form. This will call store() function at StudentController.php. At first the post details are validated using built in class, if any error will be post back to "/add-student" form. If validation is successful a new student record is created.

Step-9 Show All Added Records

After addition we have to make a page to display all the added records. For this create a file show-students.blade.php at resources/views/. Open the file and add the following code.

@extends('layouts.app')
@section('content')
<?php $l= 0; ?>
<div class="container">
<h2 class="text-center">CRUD Example in Laravel</h2>
<a class="btn btn-secondary btn-sm" href="/add-student">Add Student</a>
@if(count($students) > 0)
    <table class="table table-striped table-hover table-sm">
    <thead><th>S.No</th><th>Student Profile</th><th>Contact Details</th><th>Action</th></thead>
    <tbody>
    @foreach($students as $a)
    <?php $l++; ?>
    <tr>
    <td>{$l}</td>
    <td>
    <div class="row">
        <div class="col-6">
        <img class="img-fluid" src="{asset($a->profile_pic)}"/>
        </div>
        <div class="col-6">
        <h5><b>Name: </b>{$a->first_name} {$a->middle_name} {$a->last_name}</h5>
        <h5><b>D.O.B: </b>{$a->dob}</h5>
        <h5><b>Qualification: </b>{$a->qualification}</h5>
        </div>
    </div>
    </td>
    <td>
        <h5><b>Email: </b>{$a->email}</h5>
        <h5><b>Mobile: </b>{$a->contact}</h5>
    </td>
    <td>
    <div class="row">
    <a class="btn btn-primary btn-sm" href="/edit-student/{$a->id}">Edit</a>
    <a class="btn btn-danger btn-sm" href="/delete-student/{$a->id}" onclick="return confirm('Are you sure to delete {$a->first_name} {$a->middle_name} {$a->last_name} profile');">Delete</a>
    </div>
    </td>
    </tr>
    @endforeach
    </tbody>

    </table>
@else
<h5 class="text-center p-5">There are no records</h5>
@endif

</div>

@endsection

This will display all the added records, in the last column we add two links "Edit" & "Delete" to manage these records. For editing we use Route "/edit-student/{id}" to edit the record with unique "id" no. For Deleting we use Route "/delete-student/{id}". You can see the demo page by clicking here.

CRUD tutorial in laravel Step-10 Edit Record

For editing record we create a form edit-student.blade.php at resources/views/. Open this and add the following code.

@extends('layouts.app')
@section('content')
<div class="container">
<h2 class="text-center">Modify Student Details</h2>
<form method="post" action="/update-student">
    <div class="row">
        <div class="col">
        <label for="first_name">First Name *:</label>
        <input type="text" class="form-control @error('first_name') is-invalid @enderror" name="first_name" value="{old('first_name') ?? $a->first_name}" required>
                            @error('first_name')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{ $message }</strong>
                                        </span>
                            @enderror 
        </div>
        <div class="col">
        <label for="middle_name">Middle Name:</label>
        <input type="text" class="form-control" name="middle_name" value="{old('middle_name') ?? $a->middle_name}">
        </div>
        <div class="col">
        <label for="last_name">Last Name *:</label>
        <input type="text" class="form-control @error('last_name') is-invalid @enderror" name="last_name" value="{old('last_name') ?? $a->last_name}" required>
                            @error('last_name')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{ $message }</strong>
                                        </span>
                            @enderror
        </div>
    </div>
    <div class="row mt-1">
        <div class="col">
        <label for="dob">Date Of Birth *:</label>
        <input type="date" class="form-control @error('dob') is-invalid @enderror" name="dob" value="{old('dob') ?? $a->dob}" required>
                            @error('dob')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{ $message }</strong>
                                        </span>
                            @enderror
        </div>
        <div class="col">
        <label for="qualification">Qualification *:</label>
        <input type="text" class="form-control @error('qualification') is-invalid @enderror" name="qualification" value="{old('qualification') ?? $a->qualification}" required>
                            @error('qualification')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{ $message }</strong>
                                        </span>
                            @enderror
        </div>
        <div class="col">
        <label for="place">Place:</label>
        <input type="text" class="form-control" name="place" value="{old('place')  ?? $a->place}">
        </div>
    </div>
    <div class="row mt-1">
        <div class="col">
        <label for="profile_pic">Select image to upload:</label>
                <div class="custom-file mb-3">
                        
                            <input type="file" accept="image/*" class="custom-file-input" name="profile_pic" id="profile_pic">
                        
                            <label class="custom-file-label" for="customFile1">Upload Profile Pic</label>
                            
                          
                        </div>
        <label for="email">Email *:</label>
        <input type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{old('email') ?? $a->email}" required>
                            @error('email')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{ $message }</strong>
                                        </span>
                            @enderror
        <label for="contact">Mobile No *:</label>
        <input type="number" class="form-control @error('contact') is-invalid @enderror" name="contact" value="{old('contact') ?? $a->contact}" required>
                            @error('contact')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{ $message }</strong>
                                        </span>
                            @enderror
        </div>
        <div class="col text-center">
        
        <h5 class="text-danger"><small><b>  { $errors->first('profile_pic') } </b></small></h5>
        <span id="uploaded_pp">
        <img src="{asset($a->profile_pic)}" style="height:180px;width:120px;" class="img-thumbnail" id="pp_original"/>
        </span>
        </div>

    </div>
    <input type="text" name="id" value="{$a->id}" hidden/>
    <input type="text" name="profile_pic" value="{$a->profile_pic}" hidden/>
    <button class="btn btn-info btn-sm float float-right" type="submit">Modify Student</button>
@csrf
</form>
</div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>

  

    $(document).ready( function() {
        
       

        $(document).on('change', '#profile_pic', function(){
           
        var name = document.getElementById("profile_pic").files[0].name;
        var form_data = new FormData();
        var ext = name.split('.').pop().toLowerCase();
        if(jQuery.inArray(ext, ['png','jpg','jpeg']) == -1) 
        {
        alert("Invalid File Format (Only images allowed)");
        }
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("profile_pic").files[0]);
        var f = document.getElementById("profile_pic").files[0];
        var fsize = f.size||f.fileSize;
        if(fsize > 2000000)
        {
        alert("File Size is very big (Allowed size is Max 2MB)");
        }
        else
        {
            event.preventDefault();
            
        form_data.append("file", document.getElementById('profile_pic').files[0]);

        $.ajax({
            url:"/upload-pp",
            method:"POST",
            data: form_data,
            contentType: false,
            cache: false,
            processData: false,
            beforeSend:function(){
            $('#uploaded_pp').html("<label class='text-dark'>Profile Pic Uploading...(Fill other fields)</label>");
            },   
            
            success:function(data)
            {
            $('#pp_original').hide('slow');
            $('#uploaded_pp').html(data);
            },
            resetForm: true
        });
        }
        });

        $.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    }
                    });

	});
</script>
@endsection

This form will be same as addition form with all filled in fields. when this form is submitted update_student() function is called at StudentController.php. When ever profile pic is updated we are deleting the old pic to avoid junk in our application, this can be observed in the StudentController.php code. Once the form is submitted all fields will be validated and updated accordingly.

Step-12 Delete Record

For deleting a record Route "/delete-student/{id}" is used. This will call the function delete($id) at StudentController.php. Here based on the unique "id" field the record will be deleted and corresponding profile pic will also be deleted.

Hope you to has created this CRUD application successfully. Happy coding.

Demo Link

Laravel Laravel 7 MySQL

Search blog..!

Connect with us