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.
Read Also: Install PHP on Windows, Ubuntu Machines
Read Also: Install Apache2.4 on Windows, Ubuntu Machines
Read Also: Install Composer on Windows, Ubuntu Machines
Now Lets see the step by step procedure of our example.
Example: CRUD turorial with Student Profile
Step-1 Install Laravel Using ComposerAt first download the Laravel installer using composer as per command shown below and install it globally on your machine.
composer global require laravel/installerStep-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 ScaffoldingLaravel 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 fileRename 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=passwordStep-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 RoutesNow 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');
}
}
Read Also: Install and configure Image Class for Laravel
Step-8 Create Add Record FormCreate 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 RecordsAfter 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.

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 RecordFor 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