📖 درس ششم: مستندسازی API با OpenAPI (Swagger)
🎯 هدف این درس: آشنایی با OpenAPI Specification، تولید مستندات تعاملی با Swagger UI، نوشتن Specification استاندارد برای Endpointها و تست API از طریق مستندات.
مهمان عزیز! 👋
تا اینجا یک API کامل با امنیت و احراز هویت ساختهایم. اما اگر کسی بخواهد از API ما استفاده کند، چگونه باید بداند چه Endpointهایی وجود دارد، چه پارامترهایی نیاز است و چه پاسخی دریافت میکند؟
اینجاست که مستندسازی اهمیت پیدا میکند. یک مستند خوب، API شما را قابل استفاده، قابل فهم و حرفهای میکند. در این درس، با استاندارد OpenAPI (که قبلاً با نام Swagger شناخته میشد) آشنا میشویم و مستندات تعاملی برای API خود تولید میکنیم.
💡 OpenAPI چیست؟
OpenAPI یک استاندارد جهانی برای توصیف APIها است. با استفاده از این استاندارد، میتوانید مستندات API خود را به صورت JSON یا YAML بنویسید و با ابزارهایی مثل Swagger UI، آنها را به صورت تعاملی نمایش دهید. این استاندارد به شما امکان میدهد:
- ✅ مستندات خودکار تولید کنید.
- ✅ کلاینتهای مختلف را تولید کنید.
- ✅ تست تعاملی API را انجام دهید.
- ✅ مستندات را همیشه بهروز نگه دارید.
📋 ساختار OpenAPI Specification
یک فایل OpenAPI شامل بخشهای اصلی زیر است:
- openapi: نسخه استاندارد OpenAPI.
- info: اطلاعات کلی درباره API (عنوان، توضیحات، نسخه).
- servers: آدرسهای سرور (تولید، توسعه، تست).
- paths: تمام Endpointها و عملیاتهای آنها.
- components: اشتراکها (schemas، parameters، responses، security).
- security: روشهای احراز هویت.
- tags: برچسبها برای گروهبندی Endpointها.
openapi.yaml (ساختار کلی)
YAML
3.0.0
# نسخه استاندارد OpenAPI
openapi: "3.0.0"
# اطلاعات کلی API
info:
title: "API مدیریت کاربران"
description: "یک API کامل برای مدیریت کاربران با احراز هویت JWT"
version: "1.0.0"
contact:
name: "پشتیبانی رجستری"
email: "support@rajestary.com"
# آدرسهای سرور
servers:
- url: "https://api.rajestary.com/v1"
description: "سرور تولید"
- url: "http://localhost:8000"
description: "سرور توسعه"
# روش احراز هویت
security:
- bearerAuth: []
components:
securitySchemes:
bearerAuth:
type: "http"
scheme: "bearer"
bearerFormat: "JWT"
# مدلهای داده (Schemas)
schemas:
User:
type: "object"
properties:
id:
type: "integer"
example: 1
name:
type: "string"
example: "یونس"
email:
type: "string"
example: "younes@example.com"
role:
type: "string"
enum: ["admin", "user", "guest"]
example: "user"
created_at:
type: "string"
format: "date-time"
CreateUserRequest:
type: "object"
required:
- "name"
- "email"
- "password"
properties:
name:
type: "string"
minLength: 3
example: "یونس"
email:
type: "string"
format: "email"
example: "younes@example.com"
password:
type: "string"
minLength: 6
example: "password123"
role:
type: "string"
enum: ["admin", "user", "guest"]
default: "user"
# مسیرها (Paths)
paths:
# ... Endpointها در ادامه تعریف میشوند ...
📝 نوشتن Specification برای Endpointها
حالا بیایید Specification کامل برای API کاربران و احراز هویت را بنویسیم:
openapi.yaml (کامل)
YAML
3.0.0
# ========== مسیرهای احراز هویت ==========
paths:
"/auth/register":
post:
tags:
- "احراز هویت"
summary: "ثبتنام کاربر جدید"
description: "یک کاربر جدید با ایمیل و رمز عبور ثبتنام میکند"
operationId: "registerUser"
requestBody:
required: true
content:
"application/json":
schema:
$ref: "#/components/schemas/CreateUserRequest"
responses:
"201":
description: "ثبتنام با موفقیت انجام شد"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
example: "success"
message:
type: "string"
example: "User registered successfully"
data:
type: "object"
properties:
user:
$ref: "#/components/schemas/User"
token:
type: "string"
expires_in:
type: "integer"
"422":
description: "خطای اعتبارسنجی"
content:
"application/json":
schema:
$ref: "#/components/schemas/ValidationError"
"/auth/login":
post:
tags:
- "احراز هویت"
summary: "ورود کاربر"
description: "کاربر با ایمیل و رمز عبور وارد میشود"
operationId: "loginUser"
requestBody:
required: true
content:
"application/json":
schema:
type: "object"
required:
- "email"
- "password"
properties:
email:
type: "string"
format: "email"
example: "younes@example.com"
password:
type: "string"
example: "password123"
responses:
"200":
description: "ورود با موفقیت انجام شد"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
example: "success"
message:
type: "string"
example: "Login successful"
data:
type: "object"
properties:
user:
$ref: "#/components/schemas/User"
token:
type: "string"
expires_in:
type: "integer"
"401":
description: "اطلاعات ورود نادرست"
content:
"application/json":
schema:
$ref: "#/components/schemas/ErrorResponse"
"/auth/me":
get:
tags:
- "احراز هویت"
summary: "دریافت اطلاعات کاربر فعلی"
description: "اطلاعات کاربر احراز هویت شده را بازمیگرداند"
operationId: "getCurrentUser"
security:
- bearerAuth: []
responses:
"200":
description: "اطلاعات کاربر"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
example: "success"
data:
$ref: "#/components/schemas/User"
"401":
description: "احراز هویت نشده"
content:
"application/json":
schema:
$ref: "#/components/schemas/ErrorResponse"
# ========== مسیرهای کاربران (فقط ادمین) ==========
"/users":
get:
tags:
- "کاربران"
summary: "دریافت لیست کاربران"
description: "لیست تمام کاربران را با صفحهبندی بازمیگرداند. فقط ادمین دسترسی دارد."
operationId: "getUsers"
security:
- bearerAuth: []
parameters:
- name: "page"
in: "query"
description: "شماره صفحه"
schema:
type: "integer"
default: 1
- name: "limit"
in: "query"
description: "تعداد آیتم در هر صفحه"
schema:
type: "integer"
default: 10
maximum: 100
- name: "name"
in: "query"
description: "فیلتر بر اساس نام"
schema:
type: "string"
- name: "role"
in: "query"
description: "فیلتر بر اساس نقش"
schema:
type: "string"
enum: ["admin", "user", "guest"]
responses:
"200":
description: "لیست کاربران"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
data:
type: "object"
properties:
data:
type: "array"
items:
$ref: "#/components/schemas/User"
pagination:
type: "object"
properties:
current_page:
type: "integer"
per_page:
type: "integer"
total:
type: "integer"
total_pages:
type: "integer"
"401":
description: "احراز هویت نشده"
"403":
description: "دسترسی غیرمجاز"
post:
tags:
- "کاربران"
summary: "ایجاد کاربر جدید"
description: "یک کاربر جدید ایجاد میکند. فقط ادمین دسترسی دارد."
operationId: "createUser"
security:
- bearerAuth: []
requestBody:
required: true
content:
"application/json":
schema:
$ref: "#/components/schemas/CreateUserRequest"
responses:
"201":
description: "کاربر با موفقیت ایجاد شد"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
message:
type: "string"
data:
$ref: "#/components/schemas/User"
"422":
description: "خطای اعتبارسنجی"
"403":
description: "دسترسی غیرمجاز"
"/users/{id}":
get:
tags:
- "کاربران"
summary: "دریافت یک کاربر"
description: "اطلاعات یک کاربر خاص را بازمیگرداند"
operationId: "getUser"
security:
- bearerAuth: []
parameters:
- name: "id"
in: "path"
required: true
description: "شناسه کاربر"
schema:
type: "integer"
responses:
"200":
description: "اطلاعات کاربر"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
data:
$ref: "#/components/schemas/User"
"404":
description: "کاربر پیدا نشد"
put:
tags:
- "کاربران"
summary: "بروزرسانی کاربر"
description: "اطلاعات کاربر را بروزرسانی میکند"
operationId: "updateUser"
security:
- bearerAuth: []
parameters:
- name: "id"
in: "path"
required: true
schema:
type: "integer"
requestBody:
required: true
content:
"application/json":
schema:
type: "object"
properties:
name:
type: "string"
minLength: 3
email:
type: "string"
format: "email"
password:
type: "string"
minLength: 6
role:
type: "string"
enum: ["admin", "user", "guest"]
responses:
"200":
description: "بروزرسانی موفق"
content:
"application/json":
schema:
type: "object"
properties:
status:
type: "string"
message:
type: "string"
data:
$ref: "#/components/schemas/User"
"404":
description: "کاربر پیدا نشد"
"422":
description: "خطای اعتبارسنجی"
delete:
tags:
- "کاربران"
summary: "حذف کاربر"
description: "یک کاربر را حذف میکند. فقط ادمین دسترسی دارد."
operationId: "deleteUser"
security:
- bearerAuth: []
parameters:
- name: "id"
in: "path"
required: true
schema:
type: "integer"
responses:
"204":
description: "حذف موفق"
"404":
description: "کاربر پیدا نشد"
"403":
description: "دسترسی غیرمجاز"
🎨 راهاندازی Swagger UI
برای نمایش مستندات به صورت تعاملی، از Swagger UI استفاده میکنیم. این ابزار یک رابط کاربری زیبا برای مشاهده و تست Endpointها فراهم میکند.
swagger-ui.php
PHP
8.2
<?php
// فایل: public/swagger-ui.php
// این فایل برای نمایش Swagger UI استفاده میشود
📂 ساختار فایلهای مستندات
برای مدیریت بهتر، فایلهای OpenAPI را به این شکل سازماندهی میکنیم:
API Documentation Structure
Directory
# ساختار فایلهای مستندات
docs/
├── openapi.yaml # فایل اصلی OpenAPI
├── swagger-ui/ # فایلهای Swagger UI
│ ├── index.html
│ ├── swagger-ui.css
│ └── swagger-ui-bundle.js
└── openapi.json # نسخه JSON (برای برخی ابزارها)
# برای استفاده از CDN (روش سادهتر):
public/
└── api-docs.php # نمایش Swagger UI با CDN
🧪 تست API از طریق Swagger UI
یکی از مزیتهای بزرگ Swagger UI امکان تست Endpointها به صورت تعاملی است. برای تست احراز هویت، ابتدا باید توکن را دریافت کنید و سپس آن را در دکمه “Authorize” قرار دهید.
💡 مراحل تست با Swagger UI:
- ✅ به آدرس
https://your-domain.com/api-docs.phpبروید. - ✅ Endpoint
POST /auth/registerیاPOST /auth/loginرا باز کنید. - ✅ روی دکمه “Try it out” کلیک کنید.
- ✅ اطلاعات مورد نیاز را وارد کنید و “Execute” را بزنید.
- ✅ توکن دریافت شده را کپی کنید.
- ✅ روی دکمه “Authorize” کلیک کنید و توکن را با فرمت
Bearer {token}وارد کنید. - ✅ حالا میتوانید Endpointهای محافظتشده را تست کنید.
🔴 خطاهای رایج در مستندسازی
- ❌ اشتباه: فراموش کردن بهروزرسانی مستندات هنگام تغییر API.
- ✅ درست: مستندات را همزمان با کد بهروزرسانی کن.
- ❌ اشتباه: استفاده از مثالهای نامناسب یا نامفهوم.
- ✅ درست: از مثالهای واقعی و واضح استفاده کن.
- ❌ اشتباه: عدم مشخص کردن Security Scheme برای Endpointهای محافظتشده.
- ✅ درست: برای هر Endpoint محافظتشده،
securityرا مشخص کن.
- ❌ اشتباه: نوشتن مستندات بسیار طولانی و بدون ساختار.
- ✅ درست: از ساختار مناسب و بخشبندی استفاده کن.
💎 نکات کلیدی درس
- ✅ OpenAPI یک استاندارد جهانی برای مستندسازی API است.
- ✅ مستندات OpenAPI میتواند به صورت YAML یا JSON نوشته شود.
- ✅ Swagger UI ابزاری برای نمایش تعاملی مستندات OpenAPI است.
- ✅ Specification شامل info، servers، paths، components و security است.
- ✅
components/schemasبرای تعریف مدلهای داده استفاده میشود. - ✅
components/securitySchemesبرای تعریف روشهای احراز هویت استفاده میشود. - ✅ با Swagger UI میتوان Endpointها را به صورت تعاملی تست کرد.
- ✅ مستندات باید همیشه با کد هماهنگ باشد.
🛠️ پروژه عملی درس ششم
مهمان عزیز، حالا مستندات کامل برای API خود بنویس!
مسئله:
یک مستند کامل OpenAPI برای API محصولات خود ایجاد کن:
- ✅ مستندات کامل برای تمام Endpointهای محصولات.
- ✅ مدلهای داده (Product، CreateProductRequest، UpdateProductRequest).
- ✅ پارامترهای صفحهبندی و فیلتر.
- ✅ احراز هویت JWT برای Endpointهای محافظتشده.
- ✅ کدهای وضعیت و پاسخهای مختلف.
- ✅ مثالهای واقعی برای هر Endpoint.
🧪 راهحل پروژه (پاسخ)
مراحل پیادهسازی:
- 1️⃣ یک فایل
openapi.yamlجدید با ساختار کامل ایجاد کن. - 2️⃣ مدل
Productرا با تمام ویژگیها تعریف کن. - 3️⃣ تمام Endpointهای
/productsو/products/{id}را مستند کن. - 4️⃣ پارامترهای
category،min_price،max_priceوsearchرا اضافه کن. - 5️⃣ Swagger UI را راهاندازی کن و مستندات را تست کن.
📝 تمرینهای عملی
🧪 تمرین ۱ (ساده):
مستندات OpenAPI را برای Endpointهای احراز هویت (register، login، me) کامل کن و با Swagger UI تست کن.
🧪 تمرین ۲ (متوسط):
یک فایل openapi.json از فایل openapi.yaml تولید کن. از ابزارهای آنلاین یا کتابخانههای PHP برای تبدیل استفاده کن.
🧪 تمرین ۳ (چالشی):
یک سیستم تولید خودکار مستندات از کد PHP پیادهسازی کن. با استفاده از Reflection یا Attributes (PHP 8)، مستندات OpenAPI را از کد کنترلرها استخراج کن.
🏁 جمعبندی درس
مهمان عزیز، در این درس یاد گرفتی:
- ✅ OpenAPI Specification چیست و چرا اهمیت دارد.
- ✅ چگونه یک مستند کامل OpenAPI در قالب YAML بنویسی.
- ✅ چگونه مدلهای داده (Schemas) را در OpenAPI تعریف کنی.
- ✅ چگونه Endpointها، پارامترها و پاسخها را مستند کنی.
- ✅ چگونه احراز هویت JWT را در OpenAPI تعریف کنی.
- ✅ چگونه Swagger UI را راهاندازی و استفاده کنی.
- ✅ چگونه API خود را به صورت تعاملی با Swagger UI تست کنی.
حالا API شما مستندات حرفهای و تعاملی دارد. در درس بعدی، با تکنیکهای بهینهسازی عملکرد (Caching) آشنا میشویم. آمادهای؟ 🚀
🗺️ نقشه راه دوره: شما اینجا هستید!
برای اینکه بدانی دقیقاً کجای مسیر هستی و چه درسهایی در انتظار توست، به جدول زیر نگاه کن. درس فعلی با رنگ متفاوت مشخص شده است.
| درس | عنوان درس | آنچه یاد میگیرید |
|---|---|---|
| ۱ | مفاهیم پایه API | HTTP، REST، معماری Client-Server |
| ۲ | پیادهسازی RESTful API با PHP خام | مسیریابی، متدها، پارامترها، پاسخهای JSON |
| ۳ | مدیریت دادهها و پایگاهداده | اتصال PDO، CRUD، تراکنشها، Pagination |
| ۴ | اعتبارسنجی و احراز هویت | JWT، Roles/Permissions، Middleware |
| ۵ | امنیت API پیشرفته | OWASP Top 10، SQLi، XSS، CSRF، Rate Limiting |
| ۶ | مستندسازی API با OpenAPI | Swagger، OpenAPI Specification، مستندات تعاملی |
| ۷ | Caching و افزایش عملکرد | Redis، ETag، Cache-Control، Query Optimization |
| ۸ | API Versioning و مدیریت چرخه حیات | استراتژیهای نسخهبندی، Deprecation، Backward Compatibility |
| ۹ | تست و دیباگ API حرفهای | PHPUnit، Mocking، Logging، Postman Collection |
| ۱۰ | پروژه نهایی: API فروشگاهی | پروژه کامل فروشگاه اینترنتی با تمام قابلیتها |




نظر خود را بنویسید
با ثبت نظر، به بهبود محتوای ما کمک کنید