Loading...

Build an API-Only JWT-Powered Laravel App

View: 743    Dowload: 0   Comment: 0   Post by: hanhga   Category: Php&mySql   Fields: Other

Creating the Project

This tutorial assumes a working PHP environment has been set up, something like Homestead Improved. Let’s install our API Boilerplate. All we have to do is to clone the Github repository, with

git clone https://github.com/francescomalatesta/laravel-api-boilerplate-jwt Laravel

then run:

composer install

to install dependencies and make all the basic configuration operations. Both Laravel and JWT keys will be automatically generated.

Everything went well

Nothing more to do! Let’s build the server part of our app!

Creating the API

Before doing anything, we have to plan our application’s details and features. We are going to build a basic book wishlist, so we will be using two main entities: User and Book.

Building the User Part

The good news is that the User part is already completed.

If we open the app/Api/V1/Controllers/AuthController.php file, we can see that it already has asignup and a login method! They are not the the ones we can see in the standard AuthController in a standard new Laravel project: here they were re-implemented to have a token-based sign up and log in procedure.

Now, let’s take a look at the signup method, in particular.

public function signup(Request $request)
{
    $signupFields = Config::get('boilerplate.signup_fields');
    $hasToReleaseToken = Config::get('boilerplate.signup_token_release');

    $userData = $request->only($signupFields);

    $validator = Validator::make($userData, Config::get('boilerplate.signup_fields_rules'));

    if($validator->fails()) {
        throw new ValidationHttpException($validator->errors()->all());
    }

    User::unguard();
    $user = User::create($userData);
    User::reguard();

    if(!$user->id) {
        return $this->response->error('could_not_create_user', 500);
    }

    if($hasToReleaseToken) {
        return $this->login($request);
    }
    
    return $this->response->created();
}

As we can see from the code, we are using some options in a config file. Specifically, we are getting two values from this file:

  • boilerplate.signup_fields: the fields list we want to use for the signup operation;
  • boilerplate.signup_fields_rules: the validation rules we want our data checked against during the signup operation;

We can find all the boilerplate options in config/boilerplate.php.

There’s also another option used here: boilerplate.signup_token_release. When set to true, a token is automatically released after signup. This means that the user can start using your app immediately.

Note: for this project we are going to use 24-hour tokens. The default value for the token’s life-span is 60 minutes. This can be changed in config/jwt.php at the ttl value.

Back to our API. The actual setting for boilerplate.signup_fields is

'signup_fields' => [
    'name', 'email', 'password'
],

… and it’s fine, considering our needs. Some basic rules are there, too:

'signup_fields_rules' => [
 'name' => 'required',
 'email' => 'required|email|unique:users',
 'password' => 'required|min:6'
],

So far, we haven’t had to do anything. Also, we already have our routes in theapp/Http/api_routes.php file.


$api = app('Dingo\Api\Routing\Router');

$api->version('v1', function ($api) {

 $api->post('auth/login', 'App\Api\V1\Controllers\AuthController@login');
 $api->post('auth/signup', 'App\Api\V1\Controllers\AuthController@signup');

 ...

});

The router we’re using here is a little bit different from the normal one we see in Laravel. We are, in fact, using the custom Dingo API Router.

The user part is now complete without typing a single line of code.

The only one remaining part is the logout procedure. However, a RESTful API is stateless by definition and this is something we are going to implement in the client.

Now, we should at least test our two procedures, to be sure. The first thing to do is to migrate our database. In our terminal, let’s type

 php artisan migrate

Let’s test a basic signup procedure. We’ll open an HTTP Client and make a call to the signup route. For this article’s purposes, we will use Postman. Let’s fill our request body…

Request body filled out

… send it and wait for the result …

Result produced

Done! Our user is now added to the application. To be sure, let’s make another test. This time for thelogin.

Logging in via postman

Great! The login procedure also works fine! We don’t need anything else for the User part. Time to finish our API by implementing the Book part.

Building the Book Part

In order to implement the Book side, we will need a migration to define our schema structure, a model and, finally, a controller to handle all the operations. Let’s start with migrations. Let’s open the terminal and type

php artisan make:migration create_books_table --create=books

and a new file will be created in database/migrations. We then add the following fields in the up()method.

public function up()
{
    Schema::create('books', function (Blueprint $table) {
        $table->increments('id');

 // adding specific fields here...
        $table->string('title');
        $table->string('author_name');
        $table->integer('pages_count');

        $table->integer('user_id')->index();

        $table->timestamps();
    });
}

Time to “migrate” again, by typing

php artisan migrate

to add the new table to the schema. Now, let’s create the model, with

php artisan make:model Book

and we are done. Due to the conventions in Laravel, the Book model already “knows” that it has to work with the books table we have created. Here’s the model:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    protected $fillable = ['title', 'author_name', 'pages_count'];
}

We are going to put these fields (titleauthor_name and pages_count) into the fillable array in order to use the fill method on the update procedure (more on that soon).

Now, we have to edit our User model in order to define the relationship we will need to retrieve their related books. In app\User.php we add the following method:

public function books()
{
    return $this->hasMany('App\Book');
}

The last step is the resource controller for the Book entity. Let’s type

php artisan make:controller BookController

to create a new resource controller. Laravel will create it in the app/Http/Controllers folder. We will move it to app/Api/V1/Controllers.

We also change the namespace:

namespace App\Api\V1\Controllers;

where App is the basic namespace we have chosen for our application. By default, we can leave it as it is.

Before proceeding, we have to remember to add some use directives at the beginning of the file:

use JWTAuth;
use App\Book;
use Dingo\Api\Routing\Helpers;

The first one is the JWTAuth Facade, which we will use to retrieve our user data from the token. The second one is our model. The third is a helper we will use to quickly create every response for outputting to the client in a RESTful manner.

We must also remember to include this Helpers trait in the controller:

...

class BookController extends Controller
{
    use Helpers;

...

Now we can implement our methods:

  • index, to get the books list of a certain user;
  • show, to get a single book given its id;
  • store, to store a newly created book in the database;
  • update, to store updates on a certain book, given its id;
  • destroy, to delete an existing book from the database, given its id;

Let’s start from the first: index().

public function index()
{
    $currentUser = JWTAuth::parseToken()->authenticate();
    return $currentUser
        ->books()
        ->orderBy('created_at', 'DESC')
        ->get()
        ->toArray();
}

This is really easy to understand. We are getting our user starting from the token, and then we are returning all the related books as output. Nothing more.

We can make a step forward, to store()

public function store(Request $request)
{
    $currentUser = JWTAuth::parseToken()->authenticate();

    $book = new Book;

    $book->title = $request->get('title');
    $book->author_name = $request->get('author_name');
    $book->pages_count = $request->get('pages_count');

    if($currentUser->books()->save($book))
        return $this->response->created();
    else
        return $this->response->error('could_not_create_book', 500);
}

Like before, we are getting the current user with the JWTAuth method,parseToken()->authenticate(). Then, we are creating our instance and saving the relationship with the save method.

If everything goes right, a Created 201 response will be returned. Otherwise, the client will get a custom500 error. As we can see, it’s not just about the body: headers also will be tweaked accordingly to follow RESTful standards.

Let’s do some tests before finishing our controller. Add the following code into api_routes.php:

$api->group(['middleware' => 'api.auth'], function ($api) {
 $api->post('book/store', 'App\Api\V1\Controllers\BookController@store');
 $api->get('book', 'App\Api\V1\Controllers\BookController@index');
});

We have both routes now! Let’s get back to our HTTP Client and log in again. With our new token, let’s make some requests to store a new book and, right after, get a list of them.

We can pass the token in two ways: passing it as a simple request parameter, or in the header with this specific item: Authorization: Bearer {token_goes_here}.

That said, here’s an example of a store request and the subsequent index one.

Token filled out for storing

… and then …

Index lists out books

It works!

...

public function show($id)
{
    $currentUser = JWTAuth::parseToken()->authenticate();

    $book = $currentUser->books()->find($id);

    if(!$book)
        throw new NotFoundHttpException; 

    return $book;
}

public function update(Request $request, $id)
{
    $currentUser = JWTAuth::parseToken()->authenticate();

    $book = $currentUser->books()->find($id);
    if(!$book)
        throw new NotFoundHttpException;

    $book->fill($request->all());

    if($book->save())
        return $this->response->noContent();
    else
        return $this->response->error('could_not_update_book', 500);
}

public function destroy($id)
{
    $currentUser = JWTAuth::parseToken()->authenticate();

    $book = $currentUser->books()->find($id);

    if(!$book)
        throw new NotFoundHttpException;

    if($book->delete())
        return $this->response->noContent();
    else
        return $this->response->error('could_not_delete_book', 500);
}

...

We can finish the job by implementing the three remaining methods: showupdate and destroy.

Here they are!

We continued to use the $currentUser as an implicit “safety check”. In real world cases you should build something more robust.

It’s also possible to throw some Symfony exceptions. The API will automatically recognize them and encode in the right output format. You can find the complete supported exceptions list here.

In showupdate and destroy, we used the NotFoundHttpException to tell the client that we have not found a certain resource.

Now, all we have to do is to add the last three new routes to the api_routes.php file.

$api->group(['middleware' => 'api.auth'], function ($api) {
 $api->get('books', 'App\Api\V1\Controllers\BookController@index');
 $api->get('books/{id}', 'App\Api\V1\Controllers\BookController@show');
 $api->post('books', 'App\Api\V1\Controllers\BookController@store');
 $api->put('books/{id}', 'App\Api\V1\Controllers\BookController@update');
 $api->delete('books/{id}', 'App\Api\V1\Controllers\BookController@destroy');
});

Laravel (and Dingo) has the shortcut method resource() that we can use to bind all the routes we just saw with a single instruction.

$api->resource('books', 'App\Api\V1\Controllers\BookController');

Choose the approach you like the most.

The controller is now complete. Here it is in full!

Note: we could stumble upon some issues using PUT and DELETE verbs with some body data. If the body is always empty, try to use x-www-form-urlencoded instead of form-data. It should fix the problem.

Build an API-Only JWT-Powered Laravel App

This tutorial assumes a working PHP environment has been set up, something like Homestead Improved. Let’s install our API Boilerplate

Posted on 22-02-2016 

Comment:

To comment you must be logged in members.

Files with category

  • Twitter-like Hashtag Function in PHP

    Twitter-like Hashtag Function in PHP

    View: 0    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    If you ever want a function to hashtag and style words within a string which has '#' next to it like twitter. This piece of code will help

  • PSITS Automated Voting System

    PSITS Automated Voting System

    View: 24    Download: 3   Comment: 0

    Category: Php&mySql     Fields: none

    A free sourcecode for PSITS Automated Voting System develop in PHP programming language. The purposed of the system is to automate the process of voting and maintain the quality of data

  • PHP-University Application System

    PHP-University Application System

    View: 30    Download: 6   Comment: 0

    Category: Php&mySql     Fields: none

    Greeting from Malawi the warm heart of Africa. I developed this university registration system project just to share with the people who can make use of the project like this and at the same time for others like students who can learn from it. This...

  • School Event Management System in PHP/MSQLi

    School Event Management System in PHP/MSQLi

    View: 22    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    This School Event Management System can create school events such as Volleyball games, Basketball, Cultural presentation, Election of school officers etc . During school election Instead of having a compile list of candidates and voters this system...

  • Resort Reservation System with PayPal/Credit Card/Debit Card Payment

    Resort Reservation System with PayPal/Credit Card/Debit Card Payment

    View: 27    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    This reservation system has the ability to help its customers find available rooms, cottages and even function hall for their convenience . And in here, they will also have the idea of the room rates where they can quickly reserve for their family...

  • Activity log

    Activity log

    View: 20    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    Simple program to track user's activity log-in time and online/offline status.

  • Electricks - eCommerce

    Electricks - eCommerce

    View: 22    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    Electricks is an e-commerce website built using PHP, Bootstrap and some jQuery plugins. It has all the major functionalities of a typical e-shop. This project was used to present in Southern Luzon State University - Lucban. Feel free to use this code...

  • Simple Email App Using PHP

    Simple Email App Using PHP

    View: 18    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    Creating a simple PHP script using mail function for sending out emails.

 
File suggestion for you
Loading...
File top downloads
Loading...
Loading...
Codetitle - library source code to share, download the file to the community
Copyright © 2018. All rights reserved. codetitle Develope by Vinagon .Ltd