Hot File

Build an API-Only JWT-Powered Laravel App

View: 510    Dowload: 0   Comment: 0   Post by: hanhga  
Author: none   Category: Php&mySql   Fields: Other

10 point/2 review File has been tested

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

Introduction

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

Build an API-Only JWT-Powered Laravel App Posted on 22-02-2016  This tutorial assumes a working PHP environment has been set up, something like Homestead Improved. Let’s install our API Boilerplate 5/10 510

Comment:

To comment you must be logged in members.

Files with category

  • How to Picking the Brains of Your Customers with Microsoft’s Text Analytics

    View: 3535    Download: 0   Comment: 0   Author: none  

    How to Picking the Brains of Your Customers with Microsoft’s Text Analytics

    Category: Php&mySql
    Fields: Other

    5/1 review
    With the explosion of machine learning services in recent years, it has become easier than ever for developers to create “smart apps”. In this article, I’ll introduce you to Microsoft’s offering for providing machine-learning capabilities to apps.

  • How to MySqli Tutorial PHP MySqli Extension

    View: 274    Download: 0   Comment: 0   Author: none  

    How to MySqli Tutorial PHP MySqli Extension

    Category: Php&mySql
    Fields: Other

    0/0 review
    PHP provides three api to connect mysql Database.

  • Make Laravel Artisan Commands

    View: 247    Download: 0   Comment: 0   Author: none  

    Make Laravel Artisan Commands

    Category: Php&mySql
    Fields: Other

    0/0 review
    Artisan is the command line tool used in Laravel framework. It offers a bunch of useful command that can help you develop application quickly. Apart from Artisan available commands, you can create your own custom commands to improve your workflow.

  • Check if a Number is a Power of 2

    View: 226    Download: 0   Comment: 0   Author: none  

    Check if a Number is a Power of 2

    Category: Php&mySql
    Fields: Other

    2.25/2 review
    How to check if a number is a power of 2. To understand this question, let’s take some example.

  • Concatenate columns in MySql

    View: 292    Download: 0   Comment: 0   Author: none  

    Concatenate columns in MySql

    Category: Php&mySql
    Fields: Other

    0/1 review
    Artisan is the command line tool used in Laravel framework. It offers a bunch of useful command that can help you develop application quickly. Apart from Artisan available commands, you can create your own custom commands to improve your workflow

  • How to Query NULL Value in MySql

    View: 221    Download: 0   Comment: 0   Author: none  

    How to Query NULL Value in MySql

    Category: Php&mySql
    Fields: Other

    5/1 review
    Misunderstanding NULL is common mistake beginners do while writing MySql query. While quering in MySql they compare column name with NULL. In MySql NULL is nothing or in simple word it isUnknown Value so if you use comparison operator for NULL values...

  • How to Abstract Class in PHP

    View: 253    Download: 0   Comment: 0   Author: none  

    How to Abstract Class in PHP

    Category: Php&mySql
    Fields: Other

    0/0 review
    What is an abstract class in PHP and when to use an abstract class in your application. In this tutorial, we’ll learn about abstract class and their implementation.

  • Use Enums in Rails for Mapped Values

    View: 245    Download: 0   Comment: 0   Author: none  

    Use Enums in Rails for Mapped Values

    Category: Php&mySql
    Fields: Other

    5/1 review
    When I worked in a call center, we used to mark cases with different statuses. This allowed upper management to get a handle on where cases stood, what the bottlenecks were and flow of calls. Thankfully it has been a long time since I worked in a...

 
Newsletter Email

File suggestion for you

File top downloads

logo codetitle
Codetitle.com - library source code to share, download the file to the community
Copyright © 2015. All rights reserved. codetitle.com Develope by Vinagon .Ltd