Laravel Example

RESTful API Development

Learn how to build RESTful APIs with Laravel

API Resource

Transform model data for API responses

Resource Class

// app/Http/Resources/PostResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'content' => $this->content,
            'slug' => $this->slug,
            'author' => new UserResource($this->whenLoaded('user')),
            'created_at' => $this->created_at->format('Y-m-d H:i:s'),
            'updated_at' => $this->updated_at->format('Y-m-d H:i:s'),
        ];
    }
}

Usage Example

// Controller
public function index()
{
    $posts = Post::with('user')->paginate(10);
    return PostResource::collection($posts);
}

public function show(Post $post)
{
    return new PostResource($post->load('user'));
}

Key Points

  • Transform model data to JSON format
  • Handle nested relationships
  • Format dates and values
  • Collection support for multiple records

API Controller

RESTful API endpoints implementation

Controller Implementation

// app/Http/Controllers/Api/PostController.php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\PostResource;
use App\Http\Requests\PostRequest;
use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::with('user')
            ->latest()
            ->paginate(10);

        return PostResource::collection($posts);
    }

    public function store(PostRequest $request)
    {
        $post = $request->user()
            ->posts()
            ->create($request->validated());

        return new PostResource($post);
    }

    public function show(Post $post)
    {
        return new PostResource(
            $post->load('user', 'comments')
        );
    }

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

        return new PostResource($post);
    }

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

        return response()->json([
            'message' => 'Post deleted successfully'
        ]);
    }
}

Key Points

  • Implement RESTful actions
  • Use form requests for validation
  • Return proper status codes
  • Handle authorization with policies

API Authentication

Secure API endpoints with Laravel Sanctum

Authentication Setup

// routes/api.php
Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);

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

// app/Http/Controllers/Api/AuthController.php
public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required'
    ]);

    if (!Auth::attempt($credentials)) {
        return response()->json([
            'message' => 'Invalid credentials'
        ], 401);
    }

    $user = $request->user();
    $token = $user->createToken('auth-token')->plainTextToken;

    return response()->json([
        'token' => $token,
        'user' => new UserResource($user)
    ]);
}

API Client Usage

// Example with Axios
const api = axios.create({
    baseURL: 'http://api.example.com',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
});

// Login
const response = await api.post('/login', {
    email: 'user@example.com',
    password: 'password'
});

// Set token for subsequent requests
api.defaults.headers.common['Authorization'] = 
    `Bearer ${response.data.token}`;

// Make authenticated request
const posts = await api.get('/posts');

Key Points

  • Use Laravel Sanctum for authentication
  • Protect routes with middleware
  • Generate and manage API tokens
  • Handle client-side authentication

API Documentation

Document your API with OpenAPI/Swagger

OpenAPI Specification

openapi: 3.0.0
info:
  title: Blog API
  version: 1.0.0
  description: API for managing blog posts

paths:
  /api/posts:
    get:
      summary: List all posts
      tags: [Posts]
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: page
          schema:
            type: integer
      responses:
        200:
          description: List of posts
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Post'
    post:
      summary: Create a new post
      tags: [Posts]
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostRequest'
      responses:
        201:
          description: Post created successfully

Key Points

  • Document endpoints with OpenAPI
  • Specify request/response schemas
  • Include authentication details
  • Generate interactive documentation

API Testing

Write tests for your API endpoints

Feature Test Example

// tests/Feature/Api/PostTest.php
namespace Tests\Feature\Api;

use Tests\TestCase;
use App\Models\User;
use App\Models\Post;
use Laravel\Sanctum\Sanctum;

class PostTest extends TestCase
{
    public function test_can_list_posts()
    {
        $user = User::factory()->create();
        $posts = Post::factory()->count(3)->create();

        Sanctum::actingAs($user);

        $response = $this->getJson('/api/posts');

        $response->assertOk()
            ->assertJsonCount(3, 'data')
            ->assertJsonStructure([
                'data' => [
                    '*' => ['id', 'title', 'content']
                ]
            ]);
    }

    public function test_can_create_post()
    {
        $user = User::factory()->create();
        Sanctum::actingAs($user);

        $response = $this->postJson('/api/posts', [
            'title' => 'Test Post',
            'content' => 'Test Content'
        ]);

        $response->assertCreated()
            ->assertJsonPath('data.title', 'Test Post');

        $this->assertDatabaseHas('posts', [
            'title' => 'Test Post',
            'user_id' => $user->id
        ]);
    }
}

Key Points

  • Write feature tests for endpoints
  • Use factories for test data
  • Test authentication and authorization
  • Verify JSON responses and database state

Recommended Packages

Essential packages for API development

Package Installation

# Authentication
composer require laravel/sanctum

# API Documentation
composer require "darkaonline/l5-swagger"

# API Rate Limiting
composer require spatie/laravel-rate-limiting

# API Versioning
composer require "dingo/api"

Key Points

  • Laravel Sanctum for authentication
  • L5-Swagger for API documentation
  • Rate limiting for API protection
  • API versioning support