ساخت API با PHP از صفر
چرا ساخت API با PHP بدون درک درست از ساختار پروژه، به کدی شکننده تبدیل میشود و راه حرفهای چیست؟
اولین APIی که با PHP نوشتم، یک فایل api.php بود که با پارامترهای GET کار میکرد و همهچیز را در یک فایل جمع کرده بود. سه ماه بعد، همان فایل به بیست شاخه if-else تبدیل شد و نگهداریاش غیرممکن. آن روز یاد گرفتم که ساخت API با PHP بیش از آنکه به دانش سینتکس نیاز داشته باشد، به معماری پروژه نیاز دارد. اگر با مفهوم کلی API آشنا نیستید، API چیست نقطه شروع خوبی است.
ساختار پروژه API در PHP
ساختار پروژه، اولین تصمیمی است که تعیین میکند API شما یک سال بعد قابل نگهداری است یا نه. ساختاری که در پروژهها به آن رسیدهام، سه لایه اصلی دارد: مسیریابی (routing)، منطق دامنه (domain logic) و لایه داده (data access). هر لایه در پوشه مجزا قرار میگیرد و ورودی مشخص دارد. این تفکیک، تست هر لایه را مستقل ممکن میکند و خطاهای یک لایه را از لایههای دیگر جدا نگه میدارد.
برای پروژههای کوچک، معمولاً با یک ساختار ساده شروع میکنم: پوشه src برای کد، public برای نقطه ورود، config برای تنظیمات و vendor برای کتابخانهها. برای پروژههای بزرگتر، از الگوی MVC یا hexagonal استفاده میکنم. اگر با مفهوم Composer (Composer Package Manager) آشنا نیستید، پیشنهاد میکنم اول یک پروژه ساده را با آن بسازید تا مدیریت وابستگیها را یاد بگیرید. مفهوم کلی افزونه و کتابخانه در PHP مشابه مفهوم افزونه در وردپرس است که در افزونه وردپرس چیست توضیح داده شده است.
ساختار پروژه، سرمایه اولیه API است. اگر آن را درست بسازید، هر تغییر بعدی آسانتر است؛ اگر غلط بسازید، هر تغییر بعدی هزینه سنگینتری دارد.
مسیریابی و مدیریت درخواست
در PHP خالص، مسیریابی به این معناست که URL درخواست را تجزیه کنید و به تابع مربوطه بفرستید. سادهترین شکل این کار استفاده از پارامتر query است: /api.php?action=list. اما در REST، مسیر باید بخشی از URL باشد: /api/products/123. برای این کار، معمولاً از یک الگوی regex برای استخراج پارامترها استفاده میکنم. فریمورکهایی مثل Slim و Laravel این کار را آماده انجام میدهند و اگر پروژه بزرگ است، استفاده از آنها به جای پیادهسازی دستی توصیه میشود.
نکته مهم در مسیریابی، مدیریت متد HTTP است. یک مسیر میتواند در متد GET معنی خواندن داشته باشد و در متد POST معنی ساخت. مسیریاب باید این تفاوت را در نظر بگیرد. اگر قواعد طراحی REST را رعایت نکنید، API شما به سرعت گیجکننده میشود. راهنمای کامل اصول در اصول طراحی REST API و مفاهیم پایه در REST از مفاهیم پایه تا طراحی حرفهای آمده است.
یک اشتباه رایج در پروژههای PHP، استفاده از $_GET و $_POST به صورت خام است. این متغیرها باید همیشه پاکسازی و اعتبارسنجی شوند. یک مسیر حرفهای، ابتدا همه ورودیها را در یک ساختار استاندارد میریزد و بعد از آن استفاده میکند. این کار جلوی دسترسی مستقیم به دادههای آلوده را میگیرد.
پاسخ JSON و کدهای وضعیت HTTP
API مدرن، پاسخهایش را با JSON برمیگرداند. اگر با ساختار JSON آشنا نیستید، JSON چیست و چگونه دادهها را ساختاردهی میکند پیشنیاز مفیدی است. برای تولید JSON در PHP، از تابع json_encode استفاده میکنیم. اما نکته مهم، کد وضعیت HTTP است. یک API حرفهای، برای هر نوع پاسخ، کد وضعیت مناسب برمیگرداند. 200 برای موفقیت، 201 برای ساخت، 400 برای ورودی نامعتبر، 401 برای احراز هویت ناموفق، 404 برای منبع ناموجود و 500 برای خطای سرور.
در پروژهها، الگوی من استفاده از یک کلاس Response است که همیشه ساختار پاسخ یکسان تولید میکند. ساختار استاندارد شامل سه بخش است: status که موفق یا ناموفق بودن را میگوید، data که داده اصلی را حمل میکند و errors که خطاها را برمیگرداند. این یکنواختی، کار کلاینت را بسیار سادهتر میکند. برای کار با JSON در سناریوهای پیچیدهتر، کار با JSON در پروژههای واقعی نکات کاربردی دارد.
یک نکته کاربردی در مورد مدیریت خطا: در APIی که در محیط production کار میکند، هرگز پیام خطای خام PHP را به کاربر برنگردانید. این پیامها میتوانند اطلاعات حساسی مثل مسیر فایلها، نام دیتابیس یا حتی نسخه PHP را افشا کنند. به جای آن، یک پیام کلی برای خطاهای سرور برگردانید و جزئیات را در لاگ سرور نگه دارید.
احراز هویت و مدیریت کاربر
احراز هویت در API، از پایهایترین نیازها است. سه روش رایج در PHP عبارتند از: Basic Auth که برای محیط تست مناسب است، Bearer Token که برای بیشتر پروژهها کافی است و OAuth 2.0 که برای APIهای عمومی و اتصال به سرویسهای خارجی استفاده میشود. برای درک تفاوتها، احراز هویت در API و OAuth چیست و چگونه کار میکند را ببینید.
توکنها باید همیشه با الگوریتمهای امن تولید شوند. در PHP، تابع random_bytes انتخاب امنی برای تولید کلید است. هرگز از rand یا mt_rand برای تولید توکن استفاده نکنید چون قابل پیشبینی هستند. توکنها باید در دیتابیس به صورت hash ذخیره شوند، نه به صورت خام. اگر دیتابیس لورود به دست مهاجم بیفتد، توکنهای hash شده بیارزش هستند.
برای مدیریت سطح دسترسی، نقشهای کاربری در API باید به دقت تعریف شوند. یک API حرفهای، به جای اینکه هر کاربر دسترسی کامل داشته باشد، سطوح مختلف تعریف میکند. در PHP، این کار معمولاً با یک middleware در مسیریاب انجام میشود که قبل از اجرای هر endpoint، سطح دسترسی کاربر را بررسی میکند. اگر با مفهوم JWT آشنا نیستید، JWT چیست و چه کاربردی در احراز هویت دارد توضیح کاملی دارد.
توکن API، کلید ورود به تمام دادههای شماست. اگر آن را مثل یک رمز عبور ساده ببینید، اولین خط دفاعی را از دست دادهاید.
اعتبارسنجی و پاکسازی داده
هر ورودی API باید دو مرحله پردازش داشته باشد: اعتبارسنجی (validation) که بررسی میکند داده با فرمت مورد انتظار مطابقت دارد یا نه، و پاکسازی (sanitization) که داده را از کاراکترها یا الگوهای خطرناک تمیز میکند. این دو مرحله با هم، پایه امنیت ورودی API هستند. اگر با مفاهیم پایه امنیت آشنا نیستید، امنیت API و بهترین روشها و SQL Injection چیست و چگونه جلوگیری کنیم را ببینید.
در PHP، برای اعتبارسنجی میتوان از filter_var استفاده کرد که فیلترهای آماده برای ایمیل، URL و IP دارد. برای پاکسازی متن، htmlspecialchars و strip_tags گزینههای استاندارد هستند. اما این توابع برای همه سناریوها کافی نیستند. اگر ورودی شما قرار است در کوئری دیتابیس استفاده شود، باید از prepared statement استفاده کنید، نه از پاکسازی دستی. prepared statement جلوی SQL Injection را به صورت بنیادی میگیرد.
یک الگوی حرفهای در پروژهها: هر endpoint یک schema ورودی دارد که در قالب یک کلاس یا آرایه تعریف میشود. این schema میگوید کدام فیلد اجباری است، چه نوع دادهای میپذیرد و چه محدودیتهایی دارد. بدون این ساختار، اعتبارسنجی به کدی پراکنده تبدیل میشود که در هر endpoint متفاوت است. کتابخانههایی مثل Respect/Validation و Symfony Validator این کار را استاندارد میکنند.
نکات امنیتی که در پروژهها نجاتدهنده بودند
امنیت API، مجموعهای از تصمیمهای کوچک است. چند مورد که در پروژههای مختلف به کارم آمده:
- محدودسازی نرخ درخواست: هر توکن یا IP باید سقف درخواست داشته باشد تا در صورت سوءاستفاده، سرور از کار نیفتد.
- HTTPS اجباری: هر درخواست بدون HTTPS باید با خطای 403 رد شود.
- هدرهای امنیتی: هدرهایی مثل CORS، X-Content-Type-Options و Strict-Transport-Security باید تنظیم شوند. راهنمای کامل در هدرهای امنیتی HTTP آمده است.
- لاگ کامل: هر درخواست باید با جزئیات ثبت شود تا در صورت حمله، بتوان الگوها را تحلیل کرد.
- عدم افشای جزئیات: پیام خطاهای سرور باید عمومی باشد، نه شامل جزئیات فنی.
در پروژههای وردپرسی که API سفارشی میسازید، امنیت وردپرس هم به این مجموعه اضافه میشود. برای آشنایی با اصول، راهنمای امنیت وردپرس برای مبتدیان و امنسازی پروژههای توسعه وردپرس را ببینید. همچنین نوشتن کد PHP امن برای وردپرس نکات مهمی برای پروژههای PHP دارد.
تست و دیباگ API در PHP
تست API با ابزارهایی مثل Postman شروع میشود. Postman اجازه میدهد درخواستهای مختلف را ذخیره کنید، مجموعه تست بسازید و در CI/CD اجرا کنید. راهنمای کاربردی در تست REST API با Postman و تست API آمده است. برای تست خودکار در PHP، ابزار استاندارد PHPUnit است. با PHPUnit میتوانید تستهای واحد برای هر کلاس و تستهای integration برای مسیرهای کامل بنویسید.
دیباگ API در PHP معمولاً به چند ابزار نیاز دارد. اول، لاگگیری دقیق: هر درخواست باید در یک فایل لاگ با جزئیات ثبت شود. دوم، xdebug برای تعقیب جریان اجرا در محیط توسعه. سوم، یک ابزار مثل Query Monitor برای بررسی کوئریهای دیتابیس. چهارم، بررسی کدهای وضعیت HTTP که گاهی خودشان نشانه مشکل هستند. اگر با مفاهیم پایه دیباگ در PHP آشنا نیستید، دیباگ کردن کدهای سفارشی وردپرس نقطه شروع خوبی است.
برای مستندسازی API که بخشی از فرآیند تست هم هست، Swagger/OpenAPI استاندارد صنعت است. با آن میتوان مستندات تعاملی ساخت که هم توسعهدهندگان میتوانند تست کنند و هم کلاینتها میتوانند با آن یکپارچه شوند. راهنمای کاربردی در مستندسازی REST API با Swagger و مستندسازی API آمده است.
پرسشهای پرتکرار درباره ساخت API با PHP
آیا باید از یک فریمورک استفاده کنم یا PHP خالص؟ برای پروژههای کوچک، PHP خالص با یک مسیریاب ساده کافی است. برای پروژههای بزرگ که چند توسعهدهنده روی آن کار میکنند، فریمورکهایی مثل Laravel یا Slim ساختار و ابزارهایی میدهند که ارزش یادگیری را دارند.
چگونه میتوانم API را در وردپرس بسازم؟ وردپرس زیرساخت REST API دارد که میتوانید endpoint جدید به آن اضافه کنید. راهنمای کامل در REST API در وردپرس آمده است.
چگونه نسخهبندی API را مدیریت کنم؟ نسخه در URL، مثل /api/v1/ رایجترین روش است. وقتی تغییر ناسازگار دارید، نسخه جدید بسازید و نسخه قبلی را برای مدتی نگه دارید. جزئیات در نسخهبندی REST API آمده است.
چگونه از API در برابر حمله محافظت کنم؟ ترکیبی از rate limiting، احراز هویت مناسب، پاکسازی ورودی، HTTPS اجباری و لاگ دقیق. هیچکدام به تنهایی کافی نیستند.
آیا میتوانم API را برای استفاده در یک اپلیکیشن موبایل بهینه کنم؟ بله. کاهش حجم پاسخ، صفحهبندی مناسب، کش پذیری و endpointهای تخصصی برای نیازهای رایج موبایل، از اصول بهینهسازی است. برخی از این تکنیکها در بهینهسازی عملکرد REST API آمده است.
اگر با خطاهای رایج REST مواجه شدید، اشتباهات رایج REST API راهنمای مفیدی است. اگر PHP شما وردپرسی است و میخواهید API بسازید، ساخت منوی مدیریتی سفارشی و کار با متاباکسها در وردپرس مکملهای خوبی هستند. برای مدیریت دیتابیس که در هر API نقش دارد، اتصال به MySQL را ببینید. برای آشنایی با ابزارهای حرفهای، استفاده از REST API در وردپرس و REST API در عمل را ببینید. و برای امنیت بیشتر، چگونه REST API امن بسازیم نقطه شروع خوبی است.
درسهایی از پروژههای واقعی
سه چیز بعد از سالها کار با API در PHP یاد گرفتم. اول، ساختار پروژه را جدی بگیرید؛ اگر ابتدا درست بسازید، در تمام طول عمر پروژه سود میبرید. دوم، امنیت را از ابتدا بگنجانید نه به عنوان افزودنی. سوم، تست را در CI/CD اجرا کنید تا خطاها قبل از کاربر پیدا شوند. برای آشنایی با CI/CD در وردپرس، CI/CD برای پروژههای وردپرسی راهنمای کاملی دارد. برای مدیریت دادهها و دیتابیس، بهینهسازی پیشرفته دیتابیس وردپرس مکمل خوبی است.
اگر تجربهای از ساخت API با PHP در پروژهای واقعی دارید - چه موفق چه با چالشها - در دیدگاه بنویسید. برای من جالب است بدانم کدام بخش از ساختار یا امنیت بیشترین زمان شما را گرفته است. 🛠️