Laravel: Sıfırdan İleri Seviye

Ders 13/17 1 saat 20 dk

REST API Geliştirme

API route'ları, Resource sınıfları, Sanctum authentication ve API versioning.

REST API Geliştirme

Laravel ile modern, güvenli ve ölçeklenebilir API'ler geliştirin.

API Route'ları

// routes/api.php
// Otomatik /api prefix'i eklenir

Route::get('/posts', [PostController::class, 'index']);
Route::get('/posts/{post}', [PostController::class, 'show']);
Route::post('/posts', [PostController::class, 'store']);
Route::put('/posts/{post}', [PostController::class, 'update']);
Route::delete('/posts/{post}', [PostController::class, 'destroy']);

// Resource route
Route::apiResource('posts', PostController::class);

// Auth korumalı
Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('posts', PostController::class)->except(['index', 'show']);
    Route::get('/user', fn (Request $request) => $request->user());
});

API Controller

latest()
            ->paginate(15);
        
        return PostResource::collection($posts);
    }

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

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string',
        ]);
        
        $post = $request->user()->posts()->create($validated);
        
        return new PostResource($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 new PostResource($post);
    }

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

API Resource

php artisan make:resource PostResource
php artisan make:resource PostCollection
 $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'excerpt' => Str::limit($this->content, 150),
            'content' => $this->when($request->routeIs('posts.show'), $this->content),
            'featured_image' => $this->featured_image 
                ? asset('storage/' . $this->featured_image) 
                : null,
            'status' => $this->status,
            'view_count' => $this->view_count,
            'published_at' => $this->published_at?->toISOString(),
            'created_at' => $this->created_at->toISOString(),
            
            // İlişkiler
            'author' => new UserResource($this->whenLoaded('user')),
            'tags' => TagResource::collection($this->whenLoaded('tags')),
            'comments_count' => $this->whenCounted('comments'),
            
            // Linkler
            'links' => [
                'self' => route('api.posts.show', $this->id),
            ],
        ];
    }
}

Sanctum Authentication

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
// User model
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}

// Login endpoint
Route::post('/login', function (Request $request) {
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);
    
    if (!Auth::attempt($credentials)) {
        return response()->json([
            'message' => 'Invalid credentials'
        ], 401);
    }
    
    $user = Auth::user();
    $token = $user->createToken('api-token')->plainTextToken;
    
    return response()->json([
        'user' => new UserResource($user),
        'token' => $token,
    ]);
});

// Logout
Route::post('/logout', function (Request $request) {
    $request->user()->currentAccessToken()->delete();
    
    return response()->json(['message' => 'Logged out']);
})->middleware('auth:sanctum');

// Kullanım (Header)
// Authorization: Bearer {token}

API Response Helpers

// Başarılı response
return response()->json($data);
return response()->json($data, 201);  // Created

// Hata response
return response()->json(['message' => 'Not found'], 404);
return response()->json(['message' => 'Forbidden'], 403);

// No content
return response()->json(null, 204);

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

Önemli Noktalar

  • routes/api.php API route'ları için
  • API Resource ile response formatı standardize edilir
  • Sanctum token-based authentication sağlar
  • Rate limiting API güvenliği için önemli
  • API versioning ile backward compatibility