Laravel passport create API for your application

In the previous article Laravel api integration & configuration, we have successfully set up a Passport package in a fresh Laravel application. Now in this article, we are going to create API using the passport and we will protect all API routes and can be accessed If the user passes bearer token in each API request, otherwise the user can’t get any response.

build api using laravel passport

Now before we jump to build API using the Laravel passport package, we need to create a movie table and that will be used for the movies listing API and only accessible via a bearer token so let’s create a migration and seeder for that.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Step 1:

php artisan make:migration movies

Add below schema code to your movies migration file which will be placed in your database/migrations directory.

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('movies', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('year');
        $table->string('duration');
        $table->string('type');
        $table->string('about');
        $table->timestamps();
    });
}

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

Run migrate command to generate movies table.

php artisan migrate

To generate a seeder, execute the below code on your terminal screen.

php artisan make:seeder MoviesSeeder

Now add some dummy movies data in your MoviesSeeder seeder file which will be used for listing API.

<?php

use Carbon\Carbon;
use Illuminate\Database\Seeder;

class MoviesSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('movies')->insert([
            [
                'name'       => 'The Shawshank Redemption',
                'year'       => '1994',
                'duration'   => '142 mins',
                'type'       => 'Drama',
                'about'      => 'Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.',
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now()
            ],
            [
                'name'       => 'Forrest Gump',
                'year'       => '1994',
                'duration'   => '142 mins',
                'type'       => 'Drama, Romance',
                'about'      => 'The presidencies of Kennedy and Johnson, the events of Vietnam, Watergate, and other history unfold through the perspective of an Alabama man with an IQ of 75.',
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now()
            ]
        ]);
    }
}

Don’t forget to include MoviesSeeder in your DatabaseSeeder class file.

Run seeder command to generate dummy entries.

php artisan db:seed

Step 2:

Now we are going to work on the following API so follow the code step by steps and implement in your application:

  • Registration
  • Login
  • Movies List
  • Logout

Create an API folder at app/Http/Controllers directory and generate the following controllers:

  • AuthController
  • MoviesController

Step 3:

Open your api.php file from the routes directory and update login, registration, movies & logout API routes.

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::group([
    'prefix' => 'auth'
], function () {
    Route::post('login', 'API\AuthController@login');
    Route::post('register', 'API\AuthController@register');

    Route::group([
      'middleware' => 'auth:api'
    ], function () {
        Route::get('movies', 'API\MoviesController@getMovies');
        Route::get('logout', 'API\AuthController@logout');
    });
});

Movies [app/Movies.php]

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Movies extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'movies';

    /**
     * The primary key associated with the table.
     *
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'year', 'duration', 'type', 'about', 'created_at', 'updated_at'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [];
}

AuthController [app/Http/Controllers/API/AuthControllers]

<?php

namespace App\Http\Controllers\API;

use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class AuthController extends Controller
{
    protected $user;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Login user and create token.
     *
     * @param Request $request
     * @return void
     */
    public function login(Request $request)
    {
        // Validate incoming request
        $validator = Validator::make($request->all(), [
           'email'    => 'required',
           'password' => 'required'
        ]);

        if ($validator->fails()) {
            $data = [
                'data'    => '',
                'message' => $validator->messages()->first(),
                'status'  => 0
            ];
        } else {
            if (!Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
                $data = [
                    'data'    => '',
                    'message' => 'Unauthorized.',
                    'status'  => 0
                ];
            } else {
                $user = $request->user();
                $tokenResult = $user->createToken('Personal Access Token');
                $token = $tokenResult->token;
                $token->save();

                $data = [
                    'user_id'      => $user->id,
                    'name'         => $user->name,
                    'email'        => $user->email,
                    'token_type'   => 'Bearer',
                    'access_token' => $tokenResult->accessToken,
                    'message'      => 'You are authenticated successfully.',
                    'status'       => 1
                ];
            }
        }

        $header = array(
            'Content-Type' => 'application/json; charset=UTF-8',
            'charset'      => 'utf-8'
        );

        return response()->json(['data' => $data], 200, $header, JSON_UNESCAPED_UNICODE);
    }

    /**
     * Register new user.
     *
     * @param Request $request
     * @return void
     */
    public function register(Request $request)
    {
        // Validate incoming request
        $validator = Validator::make($request->all(), [
            'name'     => 'required',
            'email'    => 'required|email|unique:users',
            'password' => 'required'
        ]);

        if ($validator->fails()) {
            $data = [
                'data'    => '',
                'message' => $validator->messages()->first(),
                'status'  => 0
            ];
        } else {
            $userObj = new $this->user([
                'name'         => $request->name,
                'email'        => $request->email,
                'password'     => Hash::make($request->password),
            ]);
            if ($userObj->save()) {
                $data = [
                    'user_id'      => $userObj->id,
                    'name'         => $userObj->name,
                    'email'        => $userObj->email,
                    'token_type'   => 'Bearer',
                    'access_token' => $userObj->createToken('Personal Access Token')->accessToken,
                    'message'      => 'You account created successfully.',
                    'status'       => 1
                ];
            } else {
                $data = [
                    'data'    => '',
                    'message' => 'Oops! Something went wrong.',
                    'status'  => 0
                ];
            }
        }

        $header = array(
            'Content-Type' => 'application/json; charset=UTF-8',
            'charset'      => 'utf-8'
        );

        return response()->json(['data' => $data], 200, $header, JSON_UNESCAPED_UNICODE);
    }

    /**
     * Logout user (Revoke the token).
     *
     * @param Request $request
     * @return void
     */
    public function logout(Request $request)
    {
        $request->user()->token()->revoke();

        $data = [
            'data' => '',
            'message' => 'You are successfully logged out.',
            'status' => 1
        ];

        return response()->json(['data' => $data]);
    }
}

MoviesController [app/Http/Controllers/API/MoviesControllers]

<?php

namespace App\Http\Controllers\API;

use App\Movies;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\URL;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;

class MoviesController extends Controller
{
    protected $movies;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(Movies $movies)
    {
        $this->movies = $movies;
    }

    /**
     * Get list of movies.
     *
     * @return void
     */
    public function getMovies()
    {
        $moviesObj = $this->movies->get();

        $data = [
            'data'    => $moviesObj,
            'message' => 'You are successfully logged out.',
            'status'  => 1
        ];

        return response()->json(['data' => $data]);
    }
}

Now open postman in your system and start palying with your API.

  • Registration (http://localhost/passport/public/api/auth/register)
  • Login (http://localhost/passport/public/api/auth/login)
  • List Of Movies (http://localhost/passport/public/api/auth/movies)
  • Logout (http://localhost/passport/public/api/auth/logout)

Screenshots:

That’s it. You have successfully build API using the Laravel Passport package in your Laravel application.

Keep visiting for new stuff and give your feedback.

Happy Coding 😉

Laravel api integration & configuration

Recently I have worked on two Laravel mobile applications in my freelancing work and both are having android applications. So for the API authentication, I have used the Laravel Passport package. It’s very easy to authenticate each and every API using bearer token so I thought I have to create a new article on Laravel API integration & configuration which might be helpful for the new beginners who just started learning Laravel & Passport.

api integration

In this article, we are going to set up and configure Passport in fresh Laravel 6 application so please stick with the steps and later on we will build API with authentication in the next article.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Step 1:

Install the latest version of Laravel using the below commands.

composer create-project laravel/laravel passport

Step 2:

After installing Laravel go to your project directory and install laravel/ui package to setup all routes and views for the authentication purpose.

composer require laravel/ui --dev
 
php artisan ui vue --auth

npm install && npm run dev

Step 3:

Create a new database and set up a connection in your .env file.

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=passport
DB_USERNAME=root
DB_PASSWORD=

Step 4:

Now install the Passport package in our Laravel application.

composer require laravel/passport

Once your installation completed, you have to set up a few things in your config/app.php file.

'providers' => [

    Laravel\Passport\PassportServiceProvider::class,
    
],

Few updates still required on below flies so please update accordingly.

  • app/User.php
  • app/Providers/AuthServiceProvider.php
  • config/auth.php

config/auth.php

<?php

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

app/Providers/AuthServiceProvider.php

<?php

namespace App\Providers;

use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}

config/auth.php

...

/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
        'hash' => false,
    ],
],

...

Step 4:

Generate tables using migration command.

php artisan migrate

If you are geeting error like “SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `u sers_email_unique`(`email`))” during migrate, refer this article: http://bit.ly/2JiCIVO

Step 5:

Generate passport token keys for the security.

php artisan passport:install --force

That’s it. You have successfully configured a Passport in your Laravel application.

Please visit my next blog post which is related to this article where you can learn on Laravel passport create API for your application.

Keep visiting for new stuff and give your feedback.

Happy Coding 😉

Maintenance mode for Laravel application

Today I am going to show you one artisan command which is a very helpful command. Well, I am talking about the Artisan::call(‘up’) or Artisan::call(‘down’) command. Using this command you can build your own maintenance mode functionality.

This command will help you when something went wrong to your site and you need to shut down your site for the little times for the troubleshooting.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

If you just want to test this feature then open your Laravel project in the terminal and run php artisan down and then open your project in the browser and see the reflection on the site.

maintenance mode

Recently I have integrated maintenance mode functionality in my Laravel project and I must tell you that it’s too easy to set up on any Laravel project without any troubles.

Let’s say I have two types of user roles:

  1. Super Admin
  2. Business Owner

And I want to access login route & super admin group routes even If maintenance mode is enabled just like WordPress.

maintenance mode

Now let’s jump to the code and follow the steps.

Step 1:

Create new custom middleware.

php artisan make:middleware CheckForMaintenanceMode

Step 2:

After creating middleware open CheckForMaintenanceMode.php file from app/Http/Middleware directory and replace it with below code.

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;

class CheckForMaintenanceMode
{
    protected $app;

    public function __construct(Application $app)
    {
        $this->app = $app;
    }

    public function handle($request, Closure $next)
    {
        if ($this->app->isDownForMaintenance() && !$this->isBackendRequest($request)) {
            $data = json_decode(file_get_contents($this->app->storagePath() . '/framework/down'), true);

            throw new MaintenanceModeException($data['time'], $data['retry'], $data['message']);
        }

        return $next($request);
    }

    private function isBackendRequest($request)
    {
        return ($request->is('login') or $request->is('admin/*') or $request->is('api/*'));
    }
}

Inside isBackendRequest function, you can define routes that you want to allow even If maintenance mode is enabled.

Step 3:

Now we have to include CheckForMaintenanceMode middleware inside Kerel.php file and for that navigate to app/Http directory.

Here you have to do two things:

1. Add below one line of code inside protected $middleware = [ … ]

'App\Http\Middleware\CheckForMaintenanceMode',

2. Remove CheckForMaintenanceMode::class code from protected $middleware = [ … ]

\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,

Step 4:

To make your site Online/Offline, create a new form with drop-down selection(Online/Offline) somewhere in your admin panel and manage flag into the database (is_online 1/0). Whenever the admin user changes the site availability, run Artisan code based on the selection.

if ($request->get('is_online') == '1') {
    \Artisan::call('up');
} else {
    \Artisan::call('down');
}

That’s it. You have successfully created a maintenance mode functionality in your Laravel application.

Keep visiting for new stuff and give your feedback.

Happy Coding 😉

Managing Cronjobs with Laravel

Laravel provides a feature to run specific jobs through only one cron on the server.  It automatically manages all the jobs through the artisan command you don’t need to set multiple jobs on the server to execute in the specific time and specific interval.

We can manage a task on the server that executes scripts which helps in sending daily/weekly reports to email id or update records in the database from our laravel application.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

The main use of cron job is in updating the databases, sending the emails, generate reports, executing the time-consuming tasks etc. We can also delete or create files from the server with the help of Cron Job.

In the Unix based machines, there is a configuration file called crontable which is also known as Crontab. This file system manages cron jobs for that particular user in which it is placed.

To set a cron job with the script, there are various steps you have to follow.

Step1:

Create A New Command Class

Firstly, we will generate a custom command by running the following PHP artisan command in the terminal which will generate a class file in the app/Console/Commands/ directory of your laravel application.

php artisan make:console CustomCommand

After running this command you will get a message ‘Console command created successfully in your terminal and you will see there is an auto-generated class file at app/Console/Commands/CustomCommand.php with default signature. You can also assign the terminal command name by using –command option as under.

php artisan make:console CustomCommand --command=custom:command

Step 2:  

Write a script for the task

Whenever the above command will be executed in your terminal It creates a class with handle method which is called when the task is scheduled to execute. Here I am taking a sample script to delete all inactive users from the database in the handle method.

namespace App\Console\Commands;

use Illuminate\Console\Command;
use DB;

class CustomCommand extends Command {

    /**
    * The name and signature of the console command.
    * @var string
    */

    protected $signature = 'custom:command';

    /**
    * The console command description.
    * @var string
    */

    protected $description = 'Delete all inactive users';

    /**
    * Create a new command instance.
    * @return void
    */

    public function __construct()
    {
        parent::__construct();
    }

    /**
    * Execute the console command.
    * @return mixed
    */

    public function handle()
    {
        DB::table('users')->where('active', 0)->delete();
        $this->info('All inactive users are deleted successfully!');
    }
}

Now we have to register our new command with Artisan so that it will be available in the terminal. For this, we just need to add this command class name to commands array in the Kernel class that is available in app/Console/Kernel.php.

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{

    /**
    * The Artisan commands provided by your application.
    * @var array
    */

    protected $commands = [
        Commands\CustomCommand::class,
    ];

    /**
    * Define the application's command schedule.
    * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
    * @return void
    */

    protected function schedule(Schedule $schedule)
    {
        $schedule->command('custom:command')->daily();
    }
}

If you want to see your command description in terminal then run following command:

php artisan list

Now you can run your command to delete all inactive users.

php artisan custom:command

All inactive users are deleted successfully!

As you notice I schedule the command on a daily basis but there is a number of schedule frequencies that you can assign to the tasks.

The schedule tasks hourly basis

$schedule->command('custom:command')->hourly();

If you want to start the scheduler itself then you will have to add one cronjob on the server using the crontab -e command.

* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1

Using this, the Laravel command scheduler will be called by cron every minute.

Happy Coding 😉

Changing table columns with migration in Laravel 5 or above

Recently I have started working on a Laravel project and playing with migration for the first time and realized that managing the database with migration, it very easy to handle. In this tutorial, I will explain how to create the migration and how to change columns type.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Let’s create a games table with the migration, so first open your terminal and navigate to your project directory and hit below command:

php artisan make:migration create_games_table

The new migration will be placed in your database/migrations directory. Now open your games migration file and add Schema to your up method:

Schema::create('games', function (Blueprint $table) {
    $table->integer('id', '11')->increments();
    $table->integer('game_id')->nullable();
    $table->integer('title')->nullable();
    $table->string('color')->nullable();
    $table->string('long_title')->nullable();
    $table->string('square_image')->nullable();
    $table->string('circle_image')->nullable();
    $table->string('rectangle_image')->nullable();
    $table->dateTimeTz('created_at')->nullable();
    $table->dateTime('updated_at')->nullable();
    $table->dateTime('deleted_at')->nullable();
});

Run migration command to generate your games table:

php artisan migrate

Now after creating a table, I realized that I have done a mistake in the title field and I used the title as an integer type and it must have string type so now what to do. Well, it’s very easy to replace the type with the migration.

Create a new migration and add Schema to your up method:

Schema::table('games', function($table)
{
    $table->string('title')->change();
});

You just need to add change() function at the end of the chain and it will correct your type.

If you are getting below error after running migration don’t afraid.

[RuntimeException]                                                                   
Changing columns for table "games" requires Doctrine DBAL; install "doctrine/dbal".

You must install doctrine/dbal so type composer require doctrine/dbal in your terminal.

Happy Coding 😉