Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

__call و __callStatic

جزء من قسم Object Oriented Programming في رحلة PHP على Coddy — الدرس 47 من 91.

تماماً كما تعترض __get() و __set() الوصول إلى الخصائص، تعترض الطريقتان __call() و __callStatic() استدعاءات الدوال. يتم تفعيلها عندما تقوم باستدعاء دالة غير موجودة أو غير قابلة للوصول في كائن أو فئة.

تتعامل الدالة __call() مع استدعاءات الأساليب الخاصة بالكائنات (instance method calls). وهي تستقبل اسم الدالة ومصفوفة من الوسائط:

<?php
class Messenger {
    public function __call(string $name, array $arguments): string {
        return "Called '$name' with: " . implode(", ", $arguments);
    }
}

$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");

المخرجات:

Called 'sendEmail' with: Hello, World

لاستدعاءات الأساليب الساكنة (static method calls)، استخدم __callStatic(). لاحظ أنه يجب التصريح عنها كـ static:

<?php
class QueryBuilder {
    public static function __callStatic(string $name, array $arguments): string {
        if (str_starts_with($name, "findBy")) {
            $field = substr($name, 6);
            return "Finding by $field: " . $arguments[0];
        }
        return "Unknown method: $name";
    }
}

echo QueryBuilder::findByEmail("test@example.com");

المخرجات:

Finding by Email: test@example.com

تعد هذه الطرق السحرية (magic methods) قوية لإنشاء واجهات برمجة تطبيقات (APIs) انسيابية، أو تنفيذ إعادة توجيه الطرق (method forwarding)، أو بناء بناة استعلامات ديناميكية حيث تترجم أسماء الطرق إلى عمليات قاعدة بيانات. فهي تتيح لكائناتك الاستجابة بذكاء لأي استدعاء لطريقة، حتى تلك التي لم تقم بتعريفها صراحة.

challenge icon

التحدي

سهل

لنقم ببناء عميل API ديناميكي يستخدم الطرق السحرية (magic methods) للتعامل مع استدعاءات الطرق بمرونة. ستقوم بإنشاء فئة تعترض كلاً من استدعاءات طرق الكائنات (instance methods) والطرق الثابتة (static methods)، وترجمتها إلى استجابات تشبه استجابات API ذات مغزى دون تحديد كل طريقة بشكل صريح.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • ApiClient.php — أنشئ فئة ApiClient تحاكي تفاعلات API باستخدام الطرق السحرية. يجب أن تحتوي فئتك على خاصية خاصة $baseUrl يتم تعيينها من خلال المنشئ (constructor). قم بتنفيذ طريقتين سحريتين:
    • __call() — تتعامل مع استدعاءات طرق الكائنات. عندما يتم استدعاء طريقة تبدأ بـ get (مثل getUsers أو getPosts)، استخرج اسم المورد (الجزء الذي يلي "get") وأعد "GET [baseUrl]/[resource]: [arguments joined by comma]". يجب تحويل اسم المورد إلى أحرف صغيرة. إذا كانت الطريقة لا تبدأ بـ "get"، فأعد "Unknown action: [methodName]".
    • __callStatic() — تتعامل مع استدعاءات الطرق الثابتة. عندما يتم استدعاء طريقة تبدأ بـ create (مثل createUser)، استخرج اسم المورد وأعد "POST /[resource]: [arguments joined by comma]". يجب أن يكون اسم المورد بأحرف صغيرة. بالنسبة للطرق التي تبدأ بـ delete، أعد "DELETE /[resource]: [first argument]". لأي طريقة أخرى، أعد "Static action not supported: [methodName]".
  • main.php — قم بتضمين ملف ApiClient. ستتلقى ثلاثة مدخلات: عنوان URL أساسي، ومعرف مورد، وقيمة. أنشئ مثيلاً من ApiClient باستخدام عنوان URL الأساسي. ثم اطبع أربعة أسطر:
    • استدعِ طريقة get ديناميكية باستخدام معرف المورد كلاحقة لاسم الطريقة (على سبيل المثال، إذا كان المورد "Users"، فاستدعِ getUsers) مع تمرير القيمة كوسيط (argument).
    • استدعِ getProducts مع وسيطين: "electronics" و "active".
    • استدعِ الطريقة الثابتة createOrder مع تمرير القيمة كوسيط.
    • استدعِ الطريقة الثابتة deleteItem مع تمرير معرف المورد كوسيط.

تسمح الطرق السحرية لعميل API الخاص بك بالاستجابة لأي استدعاء طريقة بشكل ديناميكي. بدلاً من تحديد getUsers() و getPosts() و getProducts() وعشرات غيرها، تتعامل طريقة __call() واحدة معها جميعاً من خلال فحص اسم الطريقة واستخراج المعلومات ذات الصلة.

ورقة مرجعية

تعترض الطريقة __call() استدعاءات طرق النسخة (instance methods) التي لا توجد أو لا يمكن الوصول إليها. وهي تستقبل اسم الطريقة ومصفوفة من الوسائط:

<?php
class Messenger {
    public function __call(string $name, array $arguments): string {
        return "Called '$name' with: " . implode(", ", $arguments);
    }
}

$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");
// المخرجات: Called 'sendEmail' with: Hello, World

تعترض الطريقة __callStatic() استدعاءات الطرق الساكنة (static methods). ويجب التصريح عنها كـ static:

<?php
class QueryBuilder {
    public static function __callStatic(string $name, array $arguments): string {
        if (str_starts_with($name, "findBy")) {
            $field = substr($name, 6);
            return "Finding by $field: " . $arguments[0];
        }
        return "Unknown method: $name";
    }
}

echo QueryBuilder::findByEmail("test@example.com");
// المخرجات: Finding by Email: test@example.com

هذه الطرق السحرية (magic methods) مفيدة لإنشاء واجهات برمجة تطبيقات سلسة (fluent APIs)، أو تنفيذ إعادة توجيه الطرق (method forwarding)، أو بناء منشئي استعلامات ديناميكيين حيث تترجم أسماء الطرق إلى عمليات.

جرّب بنفسك

<?php

require_once 'ApiClient.php';

// قراءة المدخلات
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: إنشاء مثيل من ApiClient باستخدام عنوان URL الأساسي

// TODO: استدعاء طريقة get ديناميكية باستخدام المورد كلاحقة لاسم الطريقة
// تلميح: استخدم استدعاءات الطرق المتغيرة مثل $api->{"get" . $resource}($value)

// TODO: استدعاء getProducts مع وسيطين: "electronics" و "active"

// TODO: استدعاء الطريقة الثابتة createOrder مع القيمة كوسيط
// تلميح: استخدم ApiClient::createOrder($value)

// TODO: استدعاء الطريقة الثابتة deleteItem مع المورد كوسيط

?>
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming