مقالات علاء عامر

نقدم مجموعة شاملة من مقالات التعليمية الهامة في تطوير الويب لتحويل أفكارك إلى واقع رقمي

REST APIs في PHP: بناء خدمات ويب احترافية

PHP 2025-12-31 علاء عامر

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);
    }
}

💡 نصائح تحسين الأداء

  1. استخدم Cache: Redis أو Memcached للبيانات المتكررة
  2. Database Indexing: فهارس على الأعمدة المستعلم عنها
  3. Rate Limiting: حدد عدد الطلبات لكل مستخدم
  4. Compression: ضغط responses الكبيرة
  5. API Versioning: خطط للإصدارات المستقبلية

الخطوة التالية

تعلم GraphQL و API Documentation باستخدام OpenAPI/Swagger.

📩 تحتاج مساعدة في بناء API معقد؟

PHP REST API Web Services JSON HTTP Authentication
قسم المقالة
PHP

REST APIs في PHP: بناء خدمات ويب احترافية

دليل شامل لتطوير REST APIs باستخدام PHP مع أفضل الممارسات والأمان وأمثلة عملية.

REST APIs في PHP: بناء خدمات ويب احترافية
01

التواصل والاستشارة

تواصل مباشر عبر الواتساب أو الهاتف لفهم احتياجات مشروعك بدقة.

02

التخطيط والجدولة

وضع خطة عمل واضحة مع جدول زمني محدد لكل مرحلة من المشروع.

03

البرمجة والتطوير

تطوير المشروع بأحدث التقنيات لضمان الأداء والأمان العاليين.

04

المراجعة والتسليم

ختبار شامل ومراجعة دقيقة قبل التسليم النهائي للمشروع.

علاء عامر
علاء عامر

مطور ويب محترف بخبرة تزيد عن 10 سنوات في بناء حلول رقمية مبتكرة.

هل تحتاج هذه الخدمة؟

تواصل معي الآن للحصول على استشارة مجانية وعرض سعر

تواصل عبر واتساب رضاكم هو هدفنا الأسمى

عروض إضافية

  • صيانة وتحديث المواقع

    نحافظ على موقعك آمنًا ومحدّثًا دائمًا

  • ربط الأنظمة وواجهات البرمجة

    نربط أنظمتك بواجهات برمجية قوية ومرنة

  • تصميم وتحسين قواعد البيانات

    استعلامات أسرع وهيكلة أوضح وأخطاء أقل

  • تأمين المواقع والحماية المتقدمة

    حماية موقعك من التهديدات السيبرانية

  • أتمتة العمليات والمهام البرمجية

    نؤتمت المهام المتكررة ونوفّر وقتك دائمًا

لديك استفسار؟

اتصل بنا الآن

00201014714795

راسلنا عبر البريد الإلكتروني

[email protected]