How to Create and Test an API in Laravel
Tags: webdev, api, laravel
Published: 2023-06-19 17:38:00

Laravel [Eloquent](https://laravel.com/docs/9.x/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](https://kinsta.com/knowledgebase/api-endpoint/) 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:

* [Laravel version 8 or 9](https://laravel.com/docs/9.x/installation)
    
* [Composer](https://getcomposer.org/download/)
    
* [Postman](https://www.postman.com/)
    
* [XAMPP](https://www.apachefriends.org/download.html)
    
* Basic knowledge of APIs and [PHP](https://kinsta.com/php/)
    

## **API Basics**

Start by creating a new Laravel project using `composer`:

```bash
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:

```bash
cd laravel-api-create-test
php artisan serve
```

You should see the following screen:

![The Laravel landing page](https://kinsta.com/wp-content/uploads/2023/03/laravel-landing-page.png align="left")

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

```bash
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.

```php
$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.

```php
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.

```bash
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:

```php
$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.

```php
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:

```bash
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:

```php
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:

```bash
php artisan migrate
```

## **How To Test an API**

Before testing the API, ensure that the &lt;code&gt;authorize&lt;/code&gt; method inside the **app/Http/Requests/StoreProductRequest.php** is set to return &lt;code&gt;true&lt;/code&gt;.

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/](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.

```php
{
    "title":"Apple",
    "description":"Best Apples of the world"
}
```

![Creating a new product in Postman](https://kinsta.com/wp-content/uploads/2023/03/create-product-postman.png align="left")

Creating a new product in Postman

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

![Postman after clicking Send](https://kinsta.com/wp-content/uploads/2023/03/postman-code.png align="left")

After clicking on Send

Now, fetch the created products using the `GET` request. The [URL](https://kinsta.com/knowledgebase/what-is-a-url/) is the same. The results will look like the following:

![The products fetched by the GET request.](https://kinsta.com/wp-content/uploads/2023/03/get-code-products-fetched.png align="left")

## **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:

```bash
composer require laravel/sanctum
```

Then, publish the Sanctum configuration file:

```bash
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.

```php
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
```

```php
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.

```bash
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
<?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.

```bash
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
<?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')
        ]);
    }
}
```

Now run the seeder using this command:

```bash
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.

```php
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](https://kinsta.com/wp-content/uploads/2023/03/internal-server-error.png align="left")

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](http://127.0.0.1:8000/api/login) with the following body:

```php
{
    "email":"john@doe.com",
    "password":"password"
}
```

![Successful authentication and the Bearer token](https://kinsta.com/wp-content/uploads/2023/03/authentication-bearer-token.png align="left")

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

![Adding the Bearer token as the Authorization header](https://kinsta.com/wp-content/uploads/2023/03/add-bearer-token.png align="left")

## **How To Handle API Errors**

Whenever you send a request to the server, it responds. With the response, it also sends a [status code](https://kinsta.com/blog/http-status-codes/) according to the nature of the response. For example, a 200 status code indicates that the request has succeeded, and a [404](https://kinsta.com/blog/error-404-not-found/) 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.

```php
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 P.S., if you need further optimization, Kinsta’s [Database Hosting](https://kinsta.com/database-hosting/) solution simplifies setting up and managing databases for all your web projects.