REST APIs في PHP: بناء خدمات ويب احترافية
REST APIs في PHP: بناء خدمات ويب احترافية
دليل متخصص من علاء عامر - مطور ومصمم مواقع وتطبيقات احترافية
REST APIs أصبحت العمود الفقري للتطبيقات الحديثة. في هذا المقال، ستتعلم كيفية بناء APIs احترافية باستخدام PHP الخام مع أفضل الممارسات.
2️⃣ بناء API Framework بسيط
فئة الـ Router:
<?php
// classes/Router.php
class Router {
private $routes = [];
private $middleware = [];
public function get($path, $handler) {
$this->addRoute('GET', $path, $handler);
}
public function post($path, $handler) {
$this->addRoute('POST', $path, $handler);
}
public function put($path, $handler) {
$this->addRoute('PUT', $path, $handler);
}
public function delete($path, $handler) {
$this->addRoute('DELETE', $path, $handler);
}
private function addRoute($method, $path, $handler) {
$this->routes[] = [
'method' => $method,
'path' => $path,
'handler' => $handler
];
}
public function resolve() {
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// إزالة /api من البداية إذا كان موجوداً
$path = preg_replace('#^/api#', '', $path);
foreach ($this->routes as $route) {
if ($route['method'] === $method) {
$pattern = preg_replace('/\{[^}]+\}/', '([^/]+)', $route['path']);
$pattern = '#^' . $pattern . '$#';
if (preg_match($pattern, $path, $matches)) {
array_shift($matches); // إزالة المطابقة الكاملة
return $this->executeHandler($route['handler'], $matches);
}
}
}
return $this->notFound();
}
private function executeHandler($handler, $params = []) {
if (is_callable($handler)) {
return call_user_func_array($handler, $params);
}
if (is_array($handler) && count($handler) === 2) {
list($class, $method) = $handler;
$instance = new $class();
return call_user_func_array([$instance, $method], $params);
}
return $this->notFound();
}
private function notFound() {
http_response_code(404);
return json_encode(['error' => 'Route not found']);
}
}
فئة Response:
<?php
// classes/Response.php
class Response {
public static function json($data, $statusCode = 200, $headers = []) {
http_response_code($statusCode);
// إضافة headers افتراضية
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// إضافة headers مخصصة
foreach ($headers as $header => $value) {
header("$header: $value");
}
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
public static function success($data = null, $message = 'Success', $statusCode = 200) {
$response = [
'success' => true,
'message' => $message,
'timestamp' => date('Y-m-d H:i:s')
];
if ($data !== null) {
$response['data'] = $data;
}
self::json($response, $statusCode);
}
public static function error($message, $statusCode = 400, $errors = null) {
$response = [
'success' => false,
'message' => $message,
'timestamp' => date('Y-m-d H:i:s')
];
if ($errors !== null) {
$response['errors'] = $errors;
}
self::json($response, $statusCode);
}
public static function paginated($data, $currentPage, $totalPages, $totalItems) {
$response = [
'success' => true,
'data' => $data,
'pagination' => [
'current_page' => $currentPage,
'total_pages' => $totalPages,
'total_items' => $totalItems,
'has_next' => $currentPage < $totalPages,
'has_prev' => $currentPage > 1
],
'timestamp' => date('Y-m-d H:i:s')
];
self::json($response);
}
}
4️⃣ نماذج البيانات (Models)
<?php
// models/User.php
class User {
private $db;
public function __construct($database) {
$this->db = $database;
}
public function findAll($limit = 10, $offset = 0) {
$stmt = $this->db->prepare("
SELECT id, name, email, created_at
FROM users
ORDER BY created_at DESC
LIMIT :limit OFFSET :offset
");
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function findById($id) {
$stmt = $this->db->prepare("
SELECT id, name, email, created_at
FROM users
WHERE id = :id
");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
public function create($data) {
$stmt = $this->db->prepare("
INSERT INTO users (name, email, password, created_at)
VALUES (:name, :email, :password, NOW())
");
$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
$stmt->bindParam(':name', $data['name']);
$stmt->bindParam(':email', $data['email']);
$stmt->bindParam(':password', $data['password']);
if ($stmt->execute()) {
return $this->findById($this->db->lastInsertId());
}
return false;
}
public function update($id, $data) {
$setClauses = [];
$params = [':id' => $id];
foreach (['name', 'email'] as $field) {
if (isset($data[$field])) {
$setClauses[] = "$field = :$field";
$params[":$field"] = $data[$field];
}
}
if (empty($setClauses)) {
return false;
}
$stmt = $this->db->prepare("
UPDATE users
SET " . implode(', ', $setClauses) . "
WHERE id = :id
");
return $stmt->execute($params);
}
public function delete($id) {
$stmt = $this->db->prepare("DELETE FROM users WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
return $stmt->execute();
}
public function authenticate($email, $password) {
$stmt = $this->db->prepare("
SELECT id, name, email, password
FROM users
WHERE email = :email
");
$stmt->bindParam(':email', $email);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
unset($user['password']); // إزالة كلمة المرور من النتيجة
return $user;
}
return false;
}
public function count() {
$stmt = $this->db->query("SELECT COUNT(*) FROM users");
return $stmt->fetchColumn();
}
}
6️⃣ Authentication Controller
<?php
// controllers/AuthController.php
class AuthController {
private $userModel;
private $jwtAuth;
private $validator;
public function __construct() {
$database = Database::getInstance()->getConnection();
$this->userModel = new User($database);
$this->jwtAuth = new JWTAuth($_ENV['JWT_SECRET']);
$this->validator = new Validator();
}
public function login() {
$input = json_decode(file_get_contents('php://input'), true);
$rules = [
'email' => 'required|email',
'password' => 'required|string'
];
$validation = $this->validator->validate($input, $rules);
if (!$validation['valid']) {
Response::error('Validation failed', 422, $validation['errors']);
}
$user = $this->userModel->authenticate($input['email'], $input['password']);
if (!$user) {
Response::error('Invalid credentials', 401);
}
$payload = [
'user_id' => $user['id'],
'email' => $user['email'],
'name' => $user['name'],
'iat' => time(),
'exp' => time() + (24 * 60 * 60) // 24 hours
];
$token = $this->jwtAuth->encode($payload);
Response::success([
'user' => $user,
'token' => $token,
'expires_at' => date('Y-m-d H:i:s', $payload['exp'])
], 'Login successful');
}
public function register() {
$input = json_decode(file_get_contents('php://input'), true);
$rules = [
'name' => 'required|string|min:2|max:50',
'email' => 'required|email|unique:users',
'password' => 'required|string|min:6'
];
$validation = $this->validator->validate($input, $rules);
if (!$validation['valid']) {
Response::error('Validation failed', 422, $validation['errors']);
}
$user = $this->userModel->create($input);
if ($user) {
Response::success($user, 'User registered successfully', 201);
}
Response::error('Failed to register user', 500);
}
public function profile() {
$authMiddleware = new AuthMiddleware($_ENV['JWT_SECRET']);
$authMiddleware->authenticate();
$currentUser = $authMiddleware->getCurrentUser();
$user = $this->userModel->findById($currentUser['user_id']);
if ($user) {
Response::success($user);
}
Response::error('User not found', 404);
}
}
💡 نصائح تحسين الأداء
- استخدم Cache: Redis أو Memcached للبيانات المتكررة
- Database Indexing: فهارس على الأعمدة المستعلم عنها
- Rate Limiting: حدد عدد الطلبات لكل مستخدم
- Compression: ضغط responses الكبيرة
- API Versioning: خطط للإصدارات المستقبلية
الخطوة التالية
تعلم GraphQL و API Documentation باستخدام OpenAPI/Swagger.
📩 تحتاج مساعدة في بناء API معقد؟
قسم المقالة
REST APIs في PHP: بناء خدمات ويب احترافية
دليل شامل لتطوير REST APIs باستخدام PHP مع أفضل الممارسات والأمان وأمثلة عملية.
التواصل والاستشارة
تواصل مباشر عبر الواتساب أو الهاتف لفهم احتياجات مشروعك بدقة.
التخطيط والجدولة
وضع خطة عمل واضحة مع جدول زمني محدد لكل مرحلة من المشروع.
البرمجة والتطوير
تطوير المشروع بأحدث التقنيات لضمان الأداء والأمان العاليين.
المراجعة والتسليم
ختبار شامل ومراجعة دقيقة قبل التسليم النهائي للمشروع.