How to build API in Laravel

Laravel is really the best PHP framework available today. It offers so many powerful tools for quickly building amazing web sites and APIs. Only problem it has now is rising popularity of javascript powered by NodeJS. Javascript is becoming more and more popular every day and we are using it to build everything web apps, mobile apps, desktop apps … But even now PHP has it’s place and keeps fair market share. For many users which just need simple web site or API PHP is the best choice. It is supported by all servers and hosting is far cheaper then NodeJS hosting solutions.



In this tutorial we will build simple API with Laravel using API Resources.

Laravel’s resource classes allow you to expressively and easily transform your models and model collections into JSON.

Start new project

Generate new Laravel project. I will name it lapi.

laravel new lapi

Edit your env file and enter your database configuration details so you get access to your database.

Migrations

Our API will handle posts from our blog. We will generate posts table migration.

php artisan make:migration create_posts_table --create=posts

Edit create_posts_table migration file

I will just add two additional fields title and body in up() function.

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }

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

If you are using MariaDB you will probably get string length error when you try to run migrations. To fix this problem edit AppServiceProvider.php file. First import Schema and then add this line in the boot() function Schema::defaultStringLength(191);

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Schema::defaultStringLength(191);
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

Run migrations

Now we can run our migrations and create posts table in our database.

php artisan migrate

API Resources

A resource class represents a single model that needs to be transformed into a JSON structure.

We have our posts table created and now we can create PostResources. To easily generate our PostResources class we can use this command.

php artisan make:resource PostResource

PostResource.php file has been created in app/Http/Resources directory. In this file we will define how our API response should look and what fields it should return. Edit your PostResource.php file to look like example bellow.



namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'body' => $this->body,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at
        ];
    }
}

Every resource class defines a toArray() function which returns the array of attributes that should be converted to JSON response. We can access model properties directly using $this variable. Resource class will automatically proxy property and function access down to underlying model for easy access. Now when we have our PostResource defined we can return it from route or controller.

First generate Post model.

php artisan make:model Post

You don’t need to edit this file for now.

Resource Controller

We will now generate PostsController.

php artisan make:controller PostsController --resource

We added –resource flag to automatically generate functions like index(), show(), create()PostsController.php file is generated and placed in app/Http/Controllers directory. It will control how clients interact with our PostResource. Here we will define how to show, store or destroy our posts.

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Post;
use App\Http\Resources\PostResource;

class PostsController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $posts = Post::orderBy('created_at', 'desc')->paginate(10);
        return PostResource::collection($posts);
    }


    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {

        $post = $request->isMethod('put') ? Post::findOrFail($request->id) : new Post;

        $post->id = $request->input('id');
        $post->title = $request->input('title');
        $post->body = $request->input('body');

        if($post->save()) {
            return new PostResource($post);
        }

    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $post = Post::findOrFail($id);
        return new PostResource($post);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $post = Post::findOrFail($id);

        if($post->delete()) {
            return new PostResource($post);
        }
    }
}



index()

In index() function we just return collection of posts. I also ordered them by cration date and paginated them 10 per page.

store()

We used store() function to add new post or update existing post. First check if method is PUT. If that is true we will find post by it’s id and update it. If that is false we will create new post and save it in our database.

show($id)

show() function is used to find and show single post using it’s id.

destroy($id)

destroy() function will find and delete post using it’s id.

Routes

We have our PostsController defined and ready to use we just need some routes to access it’s functions. Edit your api.php file and add some routes.

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::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

// List Posts
Route::get('posts', 'PostsController@index');

// Get single Post
Route::get('post/{id}', 'PostsController@show');

// Create new Post
Route::post('post', 'PostsController@store');

// Update Post
Route::put('post', 'PostsController@store');

// Delete Post
Route::delete('post/{id}', 'PostsController@destroy');

TEST

Now when we have our API ready it’s time to test it. Run test server:

php artisan serve

Start your browser or even better Postman and go to: http://localhost:8000/api/posts. You should see JSON response and empty data[] array because we don’t have any posts yet. Lets add new post by sending POST request to http://localhost:8000/api/post. Add post content in request body as JSON object like in image bellow.

Add new post using postman

If you now send GET request to http://localhost:8000/api/posts you will see new post you have just created.

List posts

Updating existing post is similar you just need to change request type to PUT and include id of the post you want to update in the request body. Check example bellow.

Update post

Deleting post is simple as sending DELETE request to http://localhost:8000/api/post/1 and passing post id.

Delete post

To show single post by it’s id send GET request to http://localhost:8000/api/post/1

Hope all is working for you guys as it is for me and you now have functioning little API. This is just start and it can be expanded and further improved to give you far more functionality. If you have any questions please ask in comments bellow and I will try to help you.

Share with your friends