Building APIs with Laravel 12: A Comprehensive Guide

Author

Kritim Yantra

Mar 24, 2025

Building APIs with Laravel 12: A Comprehensive Guide

Laravel remains one of the most popular PHP frameworks for building robust APIs, and with Laravel 12, the process has become even more streamlined. In this guide, we'll walk through the essential steps to build a modern API with Laravel 12, covering everything from setup to deployment.

Why Choose Laravel for API Development?

Before we dive in, let's understand why Laravel is an excellent choice for API development:

  • Built-in API support with resource controllers and API routes
  • Eloquent ORM for easy database interactions
  • Robust authentication with Sanctum and Passport
  • Automatic request validation
  • Powerful error handling
  • Built-in testing tools

Step 1: Setting Up Your Laravel API Project

First, create a new Laravel project:

composer create-project laravel/laravel laravel-api
cd laravel-api

Install API:

php artisan install:api

Step 2: Configuring API Routes

Laravel separates web and API routes. All API routes go in routes/api.php:

use App\Http\Controllers\AuthController;
use App\Http\Controllers\PostController;

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('posts', PostController::class);
    Route::post('/logout', [AuthController::class, 'logout']);
});

Notice how we're using auth:sanctum middleware to protect our routes.

Step 3: Creating Models and Migrations

Let's create a Post model with migration:

php artisan make:model Post -m

Edit the migration file:

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained();
        $table->string('title');
        $table->text('content');
        $table->timestamps();
    });
}

Run the migration:

php artisan migrate

Step 4: Building the Authentication System

Create an AuthController:

php artisan make:controller AuthController

Implement the authentication methods:

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:8',
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        return response()->json([
            'token' => $user->createToken('api-token')->plainTextToken,
        ], 201);
    }

    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        $user = User::where('email', $request->email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['The provided credentials are incorrect.'],
            ]);
        }

        return response()->json([
            'token' => $user->createToken('api-token')->plainTextToken,
        ]);
    }

    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()->delete();

        return response()->json(['message' => 'Logged out']);
    }
}

Step 5: Creating the Post Controller

Generate a controller for our posts:

php artisan make:controller PostController --api

Implement the CRUD operations:

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        return Post::where('user_id', auth()->id())->get();
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string',
        ]);

        $post = Post::create([
            'user_id' => auth()->id(),
            'title' => $validated['title'],
            'content' => $validated['content'],
        ]);

        return response()->json($post, 201);
    }

    public function show(Post $post)
    {
        $this->authorize('view', $post);
        return $post;
    }

    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);

        $validated = $request->validate([
            'title' => 'sometimes|string|max:255',
            'content' => 'sometimes|string',
        ]);

        $post->update($validated);

        return $post;
    }

    public function destroy(Post $post)
    {
        $this->authorize('delete', $post);
        $post->delete();
        return response()->noContent();
    }
}

Step 6: Implementing Policies for Authorization

Create a policy for the Post model:

php artisan make:policy PostPolicy --model=Post

Define the authorization rules in app/Policies/PostPolicy.php:

public function view(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

public function delete(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

Don't forget to register the policy in app/Providers/AuthServiceProvider.php:

protected $policies = [
    Post::class => PostPolicy::class,
];

Step 7: API Response Formatting

For consistent API responses, create a trait in app/Traits/ApiResponse.php:

namespace App\Traits;

trait ApiResponse
{
    protected function success($data = null, $message = null, $code = 200)
    {
        return response()->json([
            'success' => true,
            'message' => $message,
            'data' => $data,
        ], $code);
    }

    protected function error($message = null, $code = 400, $errors = null)
    {
        return response()->json([
            'success' => false,
            'message' => $message,
            'errors' => $errors,
        ], $code);
    }
}

Now you can use this trait in your controllers for consistent responses.

Step 8: Rate Limiting

Laravel provides built-in rate limiting. Configure it in app/Http/Kernel.php:

protected $middlewareGroups = [
    'api' => [
        'throttle:api',
        // ...
    ],
];

Then configure the rates in routes/api.php:

Route::middleware(['auth:sanctum', 'throttle:60,1'])->group(function () {
    // Your protected routes here
});

Step 9: API Documentation with OpenAPI/Swagger

For API documentation, install L5-Swagger:

composer require darkaonline/l5-swagger
php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"

Add annotations to your controllers:

/**
 * @OA\Post(
 *     path="/api/register",
 *     summary="Register a new user",
 *     @OA\RequestBody(
 *         @OA\MediaType(
 *             mediaType="application/json",
 *             @OA\Schema(
 *                 @OA\Property(
 *                     property="name",
 *                     type="string"
 *                 ),
 *                 @OA\Property(
 *                     property="email",
 *                     type="string"
 *                 ),
 *                 @OA\Property(
 *                     property="password",
 *                     type="string"
 *                 ),
 *                 example={"name": "John Doe", "email": "john@example.com", "password": "secret"}
 *             )
 *         )
 *     ),
 *     @OA\Response(
 *         response=201,
 *         description="User registered successfully"
 *     ),
 *     @OA\Response(
 *         response=422,
 *         description="Validation error"
 *     )
 * )
 */

Generate the documentation:

php artisan l5-swagger:generate

Step 10: Testing Your API

Laravel provides excellent testing tools. Create a test:

php artisan make:test PostApiTest

Write some tests:

public function test_user_can_create_post()
{
    $user = User::factory()->create();
    $token = $user->createToken('test-token')->plainTextToken;

    $response = $this->withHeaders([
        'Authorization' => 'Bearer ' . $token,
    ])->postJson('/api/posts', [
        'title' => 'Test Post',
        'content' => 'This is a test post content',
    ]);

    $response->assertStatus(201)
        ->assertJson([
            'title' => 'Test Post',
            'content' => 'This is a test post content',
        ]);
}

Run the tests:

php artisan test

Step 11: Deployment Considerations

When deploying your Laravel API:

  1. Set APP_ENV=production in your .env file
  2. Generate an application key: php artisan key:generate
  3. Optimize the application: php artisan optimize
  4. Set up proper CORS configuration in config/cors.php
  5. Configure your web server (Nginx/Apache) to handle API requests
  6. Set up queue workers if using jobs
  7. Implement proper logging and monitoring

Best Practices for Laravel API Development

  1. Use API Resources: Transform your models for API responses
  2. Version your API: /api/v1/posts
  3. Implement Caching: Use Redis or other cache systems
  4. Handle Errors Gracefully: Custom error responses
  5. Use HTTPS: Always secure your API
  6. Implement Pagination: For large data sets
  7. Use API Tokens: For stateless authentication
  8. Rate Limiting: Protect against abuse
  9. Document Thoroughly: Swagger/OpenAPI documentation
  10. Monitor Performance: Use tools like Laravel Telescope

Conclusion

Building APIs with Laravel 12 is a straightforward process thanks to the framework's built-in features and excellent ecosystem. By following this guide, you've learned how to:

  • Set up a new Laravel API project
  • Implement authentication with Sanctum
  • Create CRUD operations with proper authorization
  • Format consistent API responses
  • Document your API
  • Test your endpoints
  • Prepare for deployment

Remember that API development is an iterative process. As your application grows, you'll need to consider additional aspects like:

  • API versioning strategies
  • More advanced authentication methods (OAuth2)
  • WebSocket integration for real-time features
  • Microservices architecture
  • API gateway implementation

Laravel provides all the tools you need to build professional-grade APIs that can scale with your application's needs. Happy coding!

Tags

Laravel Php

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Continue with Google

Related Posts