Build REST API with Laravel

  Smit Pipaliya   Laravel   9 months ago
Build REST API with Laravel - TechvBlogs

With the rise of Mobile Development and JavaScript frameworks, using a RESTful API is the best option to build a single interface between your data and your client.

PHP has been the most popular web language in the present times by being simple to maintain, and quick to create feature-rich web applications. Websites that are dynamic, interactive, secure, and efficient need a powerful toolset to create and consume APIs.

In this article, you will learn how to build a modern RESTful API in Laravel.

Now let's look at building a PHP RESTful API with Laravel.

Table of Contents:

  1. Prerequisites
  2. Understanding Our Application
  3. Setup New Laravel App
  4. Create MySQL Database
  5. Create Model and Migration
  6. Create Controller and Request
  7. Setup CRUD (Create, Read, Update and Delete)

Step 1: Prerequisites

Let's look at these technologies as we build our API:

Step 2: Understanding Our Application

You will build a CRUD API. CRUD means Create, Read, Update, and Delete. Our API will have the following endpoints:

Method URI Name Description
GET api/posts Index All posts return. 
GET api/posts/{id} Show Detail of a particular post by ID. 
POST api/posts Store Create a new post. 
PUT api/posts/{id} Update Update a particular post by ID. 
DELETE api/posts/{id} Destroy Delete a particular post by ID. 

Step 3: Setup New Laravel App

To get started, create a Laravel application. To do this, run the following command in your terminal:

composer create-project laravel/laravel rest-api

or, if you have installed the Laravel Installer as a global composer dependency:

laravel new rest-api

Next, start up the Laravel server if it’s not already running:

php artisan serve

You will visit your application on http://localhost:8000.

Build REST API with Laravel - TechvBlogs

Step 4: Create MySQL Database

Create a new database for your application.

Login into MySQL and run the following command:

mysql -u<username> -p<password>
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1791
Server version: 8.0.22-0ubuntu0.20.04.3 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

For Create a new Database, run the following command:

CREATE DATABASE `rest-api`;

Build REST API with Laravel - TechvBlogs

Read Also: Implement Passport In Laravel

Step 5: Create Model and Migration

We can create a Model along with migration, run the following command:

php artisan make:model Post -m

-m this argument will create Migration in Single Command.

A new file named Post.php will be created in the app directory.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'posts';

    protected $fillable = [
    	'name', 
    	'image', 
    	'description'
    ];
}

A migration file will be created in the database/migrations directory to generate the table in our database. Modify the migration file to create a column for name, description, and image, these all are fields that accept string value.

<?php

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

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

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

Open the .env file and update the credentials to access your MySQL database:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<your-database-name>
DB_USERNAME=<your-database-username>
DB_PASSWORD=<your-database-password>

Next, you will run your migration using the following command:

php artisan migrate 

Build REST API with Laravel - TechvBlogs

Step 6: Create Controller and Request

Create a resource Controller, run the following command:

php artisan make:controller PostController -r

Resource controllers make it painless to build RESTful controllers around resources.

This is the initial content of PostController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController 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)
    {
        //
    }
}

Next, create a Request file, run the following command:

php artisan make:request PostStoreRequest

As many of you already know, there are many ways to validate request in Laravel. Handling request validation is a very crucial part of any application. Laravel has some outstanding feature which deals with this very well. This is the initial content of PostStoreRequest.php:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

HTTP Status Codes

We’ve also added the response()->json() call to our endpoints. This lets us explicitly return JSON data and send an HTTP code the client can parse. The most common codes you’ll be returning will be:

  • 200 : OK. The standard success code and default option.
  • 201 : Created. Object created. Useful for the store actions.
  • 204 No Content. When the action was executed successfully, but there is no content to return.
  • 206 : Partial Content. Useful when you have to return a paginated list of resources.
  • 400 : Bad Request. The standard option for requests that cannot pass validation.
  • 401 : Unauthorized. The user needs to be authenticated.
  • 403 : Forbidden. The user is authenticated but does not have the permissions to perform an action.
  • 404 Not Found. Laravel will return automatically when the resource is not found.
  • 500 : Internal Server Error. Ideally, you will not be explicitly returning this, but if something unexpected breaks, this is what your user is going to receive.
  • 503 : Service Unavailable. Pretty self-explanatory, but also another code that is not going to be returned explicitly by the application.

Step 7: Setup CRUD (Create, Read, Update and Delete)

1. Setup Routes

Note: All API requests will need the header Accept: application/json.

Add the routes to the API routes file, to access all the functions we wrote.

Now, open routes/api.php and update the following code into that file:

Route::get('posts', "[email protected]"); // List Posts
Route::post('posts', "[email protected]"); // Create Post
Route::get('posts/{id}', "[email protected]"); // Detail of Post
Route::put('posts/{id}', "[email protected]"); // Update Post
Route::delete('posts/{id}', "[email protected]"); // Delete Post

or you can add a resource route like this:

Route::resource('posts','PostController');

Now, open app\Http\Controllers\PostController.php and update the following code into that file:

2. Read All Post

For, get the list of all posts. Update the following code into that file:

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
   // All Posts
   $posts = Post::all();

   // Return Json Response
   return response()->json([
      'posts' => $posts
   ],200);
}

Build REST API with Laravel - TechvBlogs

Get the detail of the post by ID. Update the following code into that file:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)
{
   // Post Detail 
   $post = Post::find($id);
   if(!$post){
     return response()->json([
        'message'=>'Post Not Found.'
     ],404);
   }

   // Return Json Response
   return response()->json([
      'post' => $post
   ],200);
}

Build REST API with Laravel - TechvBlogs

3. Create Post

Now, open app\Http\Requests\PostStoreRequest.php and update the following code into that file:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        if(request()->isMethod('post')) {
            return [
                'name' => 'required|string|max:258',
                'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
                'description' => 'required|string'
            ];
        } else {
            return [
                'name' => 'required|string|max:258',
                'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
                'description' => 'required|string'
            ];
        }
    }

    /**
     * Custom message for validation
     *
     * @return array
     */
    public function messages()
    {
        if(request()->isMethod('post')) {
            return [
                'name.required' => 'Name is required!',
                'image.required' => 'Image is required!',
                'description.required' => 'Descritpion is required!'
            ];
        } else {
            return [
                'name.required' => 'Name is required!',
                'description.required' => 'Descritpion is required!'
            ];   
        }
    }
}

Now, open app\Http\Controllers\PostController.php and update the following code into that file:

/**
 * Store a newly created resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function store(PostStoreRequest $request)
{
    try {
        $imageName = Str::random(32).".".$request->image->getClientOriginalExtension();

        // Create Post
        Post::create([
            'name' => $request->name,
            'image' => $imageName,
            'description' => $request->description
        ]);

        // Save Image in Storage folder
        Storage::disk('public')->put($imageName, file_get_contents($request->image));

        // Return Json Response
        return response()->json([
            'message' => "Post successfully created."
        ],200);
    } catch (\Exception $e) {
        // Return Json Response
        return response()->json([
            'message' => "Something went really wrong!"
        ],500);
    }
}

Build REST API with Laravel - TechvBlogs

4. Update Post

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function update(PostStoreRequest $request, $id)
{
    try {
        // Find Post
        $post = Post::find($id);
        if(!$post){
          return response()->json([
            'message'=>'Post Not Found.'
          ],404);
        }

        $post->name = $request->name;
        $post->description = $request->description;

        if($request->image) {
            // Public storage
            $storage = Storage::disk('public');

            // Old iamge delete
            if($storage->exists($post->image))
                $storage->delete($post->image);

            // Image name
            $imageName = Str::random(32).".".$request->image->getClientOriginalExtension();
            $post->image = $imageName;

            // Image save in public folder
            $storage->put($imageName, file_get_contents($request->image));
        }

        // Update Post
        $post->save();

        // Return Json Response
        return response()->json([
            'message' => "Post successfully updated."
        ],200);
    } catch (\Exception $e) {
        // Return Json Response
        return response()->json([
            'message' => "Something went really wrong!"
        ],500);
    }
}

Build REST API with Laravel - TechvBlogs

5. Delete Post

Delete post by ID. Update the following code into that file:

/**
 * Remove the specified resource from storage.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function destroy($id)
{
    // Post Detail 
    $post = Post::find($id);
    if(!$post){
      return response()->json([
         'message'=>'Post Not Found.'
      ],404);
    }

    // Public storage
    $storage = Storage::disk('public');

    // Iamge delete
    if($storage->exists($post->image))
        $storage->delete($post->image);

    // Delete Post
    $post->delete();

    // Return Json Response
    return response()->json([
        'message' => "Post successfully deleted."
    ],200);
}

Build REST API with Laravel - TechvBlogs

You may or may not be aware that there is an artisan command to create the symbolic link from the storage folder to the public folder.

What it does is, it allow us to access the files. By default, laravel wants you to store your files in the storage directory keeping the public directory clean only for your public files.

This command helps us to generate symbolic links.

php artisan storage:link

It'd be a good idea to follow along with the simple demo app that can be found in this GitHub repo.

Thank you for reading this article!!

Read Also: Laravel Livewire Crud Tutorial

If you have any queries or doubts about this topic please feel free to contact us. We will try to reach you.


Smit Pipaliya - Author - TechvBlogs
Smit Pipaliya
Laravel Developer