This project covers building a production-ready REST API from the ground up with proper authentication, authorisation, and structured JSON responses.
/api/v1/composer require laravel/sanctum spatie/laravel-permission
php artisan install:api
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
// routes/api.php
Route::prefix('v1')->group(function () {
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::post('/logout', [AuthController::class, 'logout']);
Route::apiResource('posts', PostController::class);
});
});
class AuthController extends Controller
{
public function login(LoginRequest $request): JsonResponse
{
if (! Auth::attempt($request->only('email', 'password'))) {
return response()->json(['message' => 'Invalid credentials'], 401);
}
$user = Auth::user();
$token = $user->createToken('api-token', $user->roles->pluck('name')->toArray());
return response()->json([
'token' => $token->plainTextToken,
'user' => new UserResource($user),
]);
}
public function logout(Request $request): JsonResponse
{
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out']);
}
}
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'excerpt' => $this->excerpt,
'author' => new UserResource($this->whenLoaded('author')),
'tags' => TagResource::collection($this->whenLoaded('tags')),
'created_at' => $this->created_at->toDateTimeString(),
];
}
}
All Comments