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. In this hands-on article, you’ll see how easy it is to create and test APIs using Laravel.

In this demonstration, 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

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

cd laravel-api-create-test
php artisan serve

You should see the following screen:

The Laravel landing page
Laravel

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

php artisan make:model Product -m

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');

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

protected $fillable = ['title', 'description'];

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

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
]);

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);
 }

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

php artisan make:request StoreProductRequest

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);

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

How To Test an API

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

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"
}
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.
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

Then, publish the Sanctum configuration file:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

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;
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,
    ],
];

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

php artisan make:controller UserController

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);
    }
}

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

php artisan make:seeder UsersTableSeeder

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' => '[email protected]',
            'password' => Hash::make('password')
        ]);
    }
}

Now run the seeder using this command:

php artisan db:seed --class=UsersTableSeeder

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']);

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
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":"[email protected]",
    "password":"password"
}
Successful authentication and the Bearer token
Successful authentication

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

Adding the Bearer token 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);
}

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 if you need further optimization, Kinsta’s Database Hosting solution simplifies setting up and managing databases for all your web projects.

Jeremy Holcombe Kinsta

Senior Editor at Kinsta, WordPress Web Developer, and Content Writer. Outside of all things WordPress, I enjoy the beach, golf, and movies. I also have tall people problems.