Queues are amazing. Queues literally make your ‘Job’ faster. But, queues are confusing and often too much a hassle to learn. In this tutorial, I will try to make it simple enough to understand yet actual enough to be used in the real world.
This is not a laravel CRUD example. There are already plenty of CRUD tutorials available you can learn by clicking here.
Note: Just a basic setup is shown between Step 1-21; just in case you have no setup ready for laravel queue tutorial. In case you have an existing setup. Jump to Step 22
Let’s get started:-
Step 1: Make a new Laravel 6 Project. Run this command in your terminal
composer create-project --prefer-dist laravel/laravel laravel-techflow360
Note: This command will install laravel v6 unless your environment doesn’t have PHP version 7.2. In case PHP 7.2 is not installed an older version of laravel will be installed.
Step 2: Navigate inside the folder and check the version and download additional packages using npm (Node.js and npm is required) using the commands
cd laravel-techflow360
php artisan -V
> Laravel Framework 6.14.0
npm install
Note: This tutorial will work without npm install too. It will basically download all the frontend packages mentioned in the package.json file.
Step 3: Build a MySQL database named laravel-techflow360.Simply use phpMyAdmin to build a database using GUI.
Step 3.1: Open the entire project folder ‘laravel-techflow360‘ in your choice of text editor (I will be using Sublime).
Step 4: Enter your database credentials in the .env file
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-techflow360
DB_USERNAME=root
DB_PASSWORD=
Note: I am not using any password in localhost so password area is blank.
Step 5: Laravel needs few tables to work efficiently. Let’s migrate them now.
php artisan migrate

MVC Framework
Ok so now that we have the basic model ready. Let us explore laravel a bit more. Laravel uses MVC (Model-View-Controller) framework. You can read about MVC framework here. Here is a quick overview.
The model manages the data, logic and the algorithm of the application.
The view is for the representation of the chart, diagram etc. Users only get to see this part.
The controller receives the input and converts it as a command for the view or the model.
> Hello Model
Step 6: Let’s create a model Student
php artisan make:model Student --migration
You will get an output like this:-
Model created successfully.
Created Migration: 2020_02_08_131311_create_students_table
Step 7: Navigate to database\migration\2020_02_08_131311_create_students_table file in your text editor and modify it like this. (Pro Tip: Use Ctrl+P to quickly search for files in Sublime). Postmodification your file will look like this:-
<?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->bigIncrements('id');
$table->timestamps();
$table->string('name');
$table->string('roll');
$table->string('result');
$table->string('mobile');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('students');
}
}
We modified and added name, roll, result and mobile column in the schema.
Step 8: Migrate the table now
php artisan migrate
Step 9: Now open the file app\Student.php and modify it accordingly
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
protected $fillable = [
'name',
'roll',
'result',
'mobile'
];
}
>Hello Controller
Step 10: Create a Controller
php artisan make:controller StudentController --resource
Note:
–resource is a clever little command that automatically creates a CRUD layout in the controller and a single command in the route file web.php creates multiple paths to the controller. Here is the initial skeleton of the controller with path app\Http\Controllers\StudentController. For simplicity of the tutorial, we will only concern ourselves with functions index(), create() and store()
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class StudentController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
Step 11: Navigate to routes\web.php and add the following line (Route::resource(‘students’, ‘StudentController’);). Your web.php file should look like this
Route::get('/', function () {
return view('welcome');
});
Route::resource('students', 'StudentController');
Step 12: Add use App\Contact; in StudentController. It should look like
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Student;
class StudentController extends Controller
{
Step 13: Modify the Student controller index(),create(),store() function like this:-
public function index()
{
$students = Student::all();
return view('students.index', compact('students'));
}
public function create()
{
return view('students.create');
}
public function store(Request $request)
{
$request->validate([
'name'=>'required',
'roll'=>'required',
'mobile'=>'required',
'result'=>'required'
]);
$student = new Student([
'name' => $request->get('name'),
'roll' => $request->get('roll'),
'mobile' => $request->get('mobile'),
'result' => $request->get('result')
]);
$student->save();
return redirect('/students')->with('success', 'Student saved!');
}
>Hello View
Step 14: In resources/views folder create a template.blade.php file
cd resources/views
touch template.blade.php
Step 15: Open resources/views/template.blade.php and modify it
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Techflow360 Queue Tutorial</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<style>
* {
box-sizing: border-box;
}
input[type=text], select, textarea {
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
resize: vertical;
}
label {
padding: 12px 12px 12px 0;
display: inline-block;
}
input[type=submit] {
background-color: #4CAF50;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}
input[type=submit]:hover {
background-color: #45a049;
}
.container {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
.col-25 {
float: left;
width: 25%;
margin-top: 6px;
}
.col-75 {
float: left;
width: 75%;
margin-top: 6px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
.col-25, .col-75, input[type=submit] {
width: 100%;
margin-top: 0;
}
}
</style>
</head>
<body>
<div class="container">
@yield('main')
</div>
</body>
</html>
Step 16: Create a new repository named students inside resources/views
mkdir students
Step 17: Navigate inside students and create a blade file named create.blade.php
cd students
touch create.blade.php
Step 18: Open create.blade.php and enter the following code
@extends('template')
@section('main')
<div class="row">
<div class="col-sm-8 offset-sm-2">
<h1 class="display-3">Add a Student</h1>
<div>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div><br />
@endif
<form method="post" action="{{ route('students.store') }}">
@csrf
<div class="form-group" class="col-25">
<label for="name">Full Name:</label>
<input type="text" class="form-control" name="name"/>
</div>
<div class="form-group" class="col-25">
<label for="roll">Roll Number:</label>
<input type="text" class="form-control" name="roll"/>
</div>
<div class="form-group" class="col-25">
<label for="mobile">Mobile Number:</label>
<input type="text" class="form-control" name="mobile"/>
</div>
<div class="form-group" class="col-25">
<label for="result">Result:</label>
<input type="text" class="form-control" name="result"/>
</div>
<div class="row">
<input type="submit"></input>
</div>
</form>
</div>
</div>
</div>
@endsection
Step 19: Similarly create an index.blade.php file inside students folder
@extends('template')
@section('main')
<div class="row">
<div class="col-sm-12">
<h1 class="display-3">Students</h1>
<a class="btn btn-primary" href="{{route('students.create')}}">ADD A NEW STUDENT</a>
<table class="table table-striped">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Roll</td>
<td>Result</td>
<td>Mobile</td>
</tr>
</thead>
<tbody>
@foreach($contacts as $contact)
<tr>
<td>{{$contact->id}}</td>
<td>{{$contact->name}}</td>
<td>{{$contact->roll}}</td>
<td>{{$contact->result}}</td>
<td>{{$contact->mobile}}</td>
</tr>
@endforeach
</tbody>
</table>
<div>
</div>
@endsection
Step 20: Start the server and run the code
php artisan serve
>Laravel development server started: http://127.0.0.1:8000
Step 21: Navigate to your URL in my case it’s 127.0.0.1:8000
http://127.0.0.1:8000/students
>Hello JOB/QUEUE
Let us now start with our actual tutorial of laravel queue. I knowwwww!!!! Gosh! In my defence, basics are important too.
Step 22: Open .env file again and change the queue driver/connection to the database. Additionally, enter two more variables which will be used later. API Key and Sender ID are required to send SMS. It is available for FREE at www.pingsms.in. Check out my Github Repo to learn about the different features of the API.
QUEUE_CONNECTION=database
PINGSMS_API_KEY=NisD1NYRZaye0SuAmzE4wbIsKT0t0kdjjfu82923920203283djna
PINGSMS_SENDERID=PNGDMO
Step 23: We will use the database so we need a job table. Run
php artisan queue:table
Step 24: Migrate the table
php artisan migrate
Step 25: Create a new Job to send SMS. (Don’t worry you can use jobs for mail also)
php artisan make:job SendSMSJob
Step 26: Open the SendSMSJob file in located in app\Jobs
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use DB;
class SendSMSJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;
protected $details;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$students=$students=DB::select('SELECT * FROM students WHERE id=?',[$this->details]);;
foreach($students AS $student){
$curl = curl_init();
$apiKey=env("PINGSMS_API_KEY"); //Enter The API Key Here
$senderId=env("PINGSMS_SENDERID"); //Your SenderId. PNGSMS is default senderId
$mobileNumber=$student->mobile; //10 digit phone number separated by comma (,)
$language="1";
$product="1";
$message="Dear $student->name,
Your Roll No. is $student->roll and your Result is $student->result.";
$message=urlencode($message);// Encode the message to send it through URL
curl_setopt_array($curl, array(
CURLOPT_URL => "https://www.pingsms.in/api/sendsms?key=".$apiKey."&sender=".$senderId."&mobile=".$mobileNumber."&language=".$language."&product=".$product."&message=".$message,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array("X-Authorization: ".$apiKey),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response."\n";
}
}
}
}
Step 27: Dispatch the Job in Student controller in the store function. Modified store() will look like:-
public function store(Request $request)
{
$request->validate([
'name'=>'required',
'roll'=>'required',
'mobile'=>'required',
'result'=>'required'
]);
$student = new Student([
'name' => $request->get('name'),
'roll' => $request->get('roll'),
'mobile' => $request->get('mobile'),
'result' => $request->get('result')
]);
$student->save();
dispatch(new \App\Jobs\SendSMSJob($student->id)); //Dispatch the JOB Here
return redirect('/students')->with('success', 'Student saved!');
}
Step 28: Run the Job(No Longer required in laravel v6)
php artisan queue:work
I use queue:work in production and queue:listen in local, Check my old article to know why. A better way to run the queue can be found here.
Feel free to comment below if you have additional queries.
Source code is available at https://github.com/sa1if3/laravel-techflow360/
Md. Saifur Rahman is a Full Stack Django and Laravel Developer. Additionally, he loves to spend time learning and researching about the Internet of Things (IoT). He loves to share his work and contribute to helping fellow developers.