DEV Community

Cover image for How to Create and Test an API in Laravel
Kinsta
Kinsta

Posted on • Originally published at kinsta.com

How to Create and Test an API in Laravel

Laravel Eloquent is an easy way to interact with your database. It is an object-relational mapper (ORM) that simplifies the complexities of databases by providing a model to interact with tables.

As such, Laravel Eloquent has excellent tools for creating and testing APIs to support your development. Read on to see how easy it is to create and test APIs using Laravel.

You’ll start by creating a model that you can use to build the API and database table. Then, you’ll see how to add a controller as a business logic layer and a route to complete the API. You’ll then learn how to perform testing APIs using Postman before finally focusing on authentication and error handling.

Prerequisites

To get started, here’s what you’ll need:

API Basics

Start by creating a new Laravel project using composer:

composer create-project laravel/laravel laravel-api-create-test
Enter fullscreen mode Exit fullscreen mode

To start the server, execute the following command, which runs the application server on port 8000:

cd laravel-api-create-test
php artisan serve
Enter fullscreen mode Exit fullscreen mode

You should see the following screen:

The Laravel landing page

Then, create a model with a -m flag for the migration using the code below:

php artisan make:model Product -m
Enter fullscreen mode Exit fullscreen mode

Now upgrade the migration file to include the required field. Add title and description fields for the product model and these two table fields inside the database/migrations/{date_stamp}_create_products_table.php file.

$table->string('title');
$table->longText('description');
Enter fullscreen mode Exit fullscreen mode

The next step is to make these fields fillable. Inside app/Models/Product.php, make title and description fillable fields.

protected $fillable = ['title', 'description'];
Enter fullscreen mode Exit fullscreen mode

How To Create a Controller

Now, create a controller file for the product by executing the following command. This will create the app/Http/Controllers/Api/ProductController.php file.

php artisan make:controller Api\\ProductController --model=Product
Enter fullscreen mode Exit fullscreen mode

Now, add the logic for creating and retrieving the products. Inside the index method, add the following code to retrieve all the products:

$products = Product::all();
return response()->json([
    'status' => true,
    'products' => $products
]);
Enter fullscreen mode Exit fullscreen mode

After that, you must add a StoreProductRequest class for storing the new products in the database. Add the following class at the top of the same file.

public function store(StoreProductRequest $request)
 {
    $product = Product::create($request->all());

    return response()->json([
        'status' => true,
        'message' => "Product Created successfully!",
        'product' => $product
    ], 200);
 }
Enter fullscreen mode Exit fullscreen mode

Now, you’ll create the request, which you can do by executing the following command:

php artisan make:request StoreProductRequest
Enter fullscreen mode Exit fullscreen mode

If you want to add validations, you can use the app/Http/Requests/StoreProductRequest.php file. For this demonstration, there are no validations.

How To Create a Route

The final step before testing the API is adding a route. To do so, add the following code inside the routes/api.php file. Add the use statement at the beginning of the file and the Route statement in the body:

use App\Http\Controllers\Api\ProductController;
Route::apiResource('products', ProductController::class);
Enter fullscreen mode Exit fullscreen mode

Before you start testing the API, ensure that the products table is in your database. If it doesn’t exist, create one using a control panel like XAMPP. Alternatively, you can execute the following command to migrate the database:

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

How To Test an API

Before testing the API, ensure that the <code>authorize</code> method inside the app/Http/Requests/StoreProductRequest.php is set to return <code>true</code>.

Now, you can create a new product using Postman. Start by hitting a POST request to this URL: http://127.0.0.1:8000/api/products/. Because it’s a POST request for creating a new product, you must pass a JSON object with a title and description.

{
    "title":"Apple",
    "description":"Best Apples of the world"
}
Enter fullscreen mode Exit fullscreen mode

Creating a new product in Postman

Creating a new product in Postman

After clicking the Send button, you should see the following:

Postman after clicking Send

After clicking on Send

Now, fetch the created products using the GET request. The URL is the same. The results will look like the following:

The products fetched by the GET request.

How To Authenticate an API Using Sanctum

Authentication is crucial when securing an API. Laravel makes it easy by providing the functionality of the Sanctum token, which you can use as middleware. It secures the API using tokens generated when the user logs in using the correct credentials. Remember that users can’t access the secured API without a token.

The first step to adding authentication is to add a Sanctum package using the code below:

composer require laravel/sanctum
Enter fullscreen mode Exit fullscreen mode

Then, publish the Sanctum configuration file:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Enter fullscreen mode Exit fullscreen mode

After that, add Sanctum’s token as middleware. Inside the app/Http/Kernel.php file, use the following class and replace middlewareGroups with the following code in the protected middleware groups’ API.

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
Enter fullscreen mode Exit fullscreen mode
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        EnsureFrontendRequestsAreStateful::class,
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];
Enter fullscreen mode Exit fullscreen mode

The next step is to create a UserController and add the code to get the token to authenticate.

php artisan make:controller UserController
Enter fullscreen mode Exit fullscreen mode

After creating the UserController, navigate to the app/Http/Controllers/UserController.php file and replace the existing code with the following code:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
    // 

    function index(Request $request)
    {
        $user= User::where('email', $request->email)->first();
        // print_r($data);
            if (!$user || !Hash::check($request->password, $user->password)) {
                return response([
                    'message' => ['These credentials do not match our records.']
                ], 404);
            }

             $token = $user->createToken('my-app-token')->plainTextToken;

            $response = [
                'user' => $user,
                'token' => $token
            ];

             return response($response, 201);
    }
}
Enter fullscreen mode Exit fullscreen mode

Before you can test the authentication, create a user employing seeders. The following command creates a UsersTableSeeder file.

php artisan make:seeder UsersTableSeeder
Enter fullscreen mode Exit fullscreen mode

Inside the database/seeders/UsersTableSeeder.php file, replace the existing code with the following code to seed the user:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            'name' => 'John Doe',
            'email' => 'john@doe.com',
            'password' => Hash::make('password')
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now run the seeder using this command:

php artisan db:seed --class=UsersTableSeeder
Enter fullscreen mode Exit fullscreen mode

The last step left in the authentication flow is to use the created middleware to protect the route. Navigate to the routes/api.php file and add the products route inside the middleware.

use App\Http\Controllers\UserController;

Route::group(['middleware' => 'auth:sanctum'], function () {
    Route::apiResource('products', ProductController::class);
});

Route::post("login",[UserController::class,'index']);
Enter fullscreen mode Exit fullscreen mode

After adding a route to the middleware, you’ll get an internal server error if you try to fetch the products.

An internal server error after adding a route

But once you log in, get a token, and use it in the header, it will authenticate you and start working. You can send a POST request to http://127.0.0.1:8000/api/login with the following body:

{
    "email":"john@doe.com",
    "password":"password"
}
Enter fullscreen mode Exit fullscreen mode

Successful authentication and the Bearer token

Use the token received as a Bearer token and add it as the Authorization header.

Adding the Bearer token as the Authorization header

How To Handle API Errors

Whenever you send a request to the server, it responds. With the response, it also sends a status code according to the nature of the response. For example, a 200 status code indicates that the request has succeeded, and a 404 suggests that the server can’t find the requested resource.

However, a status code isn’t enough. A human-readable error message is required. Laravel comes with many ways to handle errors. You can use a try-catch block, the fallback method, or send a custom response. The following code you added to the UserController demonstrates this.

if (!$user || !Hash::check($request->password, $user->password)) {
    return response([
        'message' => ['These credentials do not match our records.']
    ], 404);
}
Enter fullscreen mode Exit fullscreen mode

Summary

Laravel’s Eloquent Model makes it effortless to create, validate, and test APIs. Its object-relational mapping provides a straightforward approach to interacting with the database.

Furthermore, acting as middleware, Laravel’s Sanctum token can help you to secure your APIs quickly.

And P.S., if you need further optimization, Kinsta’s Database Hosting solution simplifies setting up and managing databases for all your web projects.

Top comments (0)