انتقل إلى محتوى الدرس
الدرس 72
دورة PHP

الأصناف المجهولة وتسلسل الكائنات وفحص الأصناف في PHPPHP Anonymous Classes Object Serialization and Reflection Checks

أنشئ كائنات فورية عبر new class، وخزّن الكائنات بأمان عبر __serialize و__unserialize، وافحص الأصناف والدوال في وقت التشغيل.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

يتيح الصنف المجهول (new class { ... }) تعريف وإنشاء كائن فوري للاستخدام لمرة واحدة في نفس السطر دون الحاجة لإنشاء ملف أو اسم صنف منفصل.

  • مرّر معاملات البناء مباشرة بعد الكلمة new class($arg1, $arg2) { ... } تماماً مثل إنشاء كائن من صنف عادي.
  • يمكن للصنف المجهول أن يحتوي على خصائص محددة النوع وثوابت ودالة بناء ودوال عامة أو خاصة.
  • استخدم الأصناف المجهولة للمساعدات المحلية السريعة أو الكائنات المؤقتة داخل الاختبارات.

يمرر التعبير new class("CheckoutJob") النص إلى دالة البناء الداخلية ويُرجع فوراً كائناً جاهزاً للاستخدام.

مخطط توضيحي: محاكي الأصناف المجهولة وتسلسل الكائنات وفحص الأصناف في PHP
PHP
<?php
$timer = new class("CheckoutJob") {
    public function __construct(public string $label) {}
    public function summary(int $ms): string {
        return "[{$this->label}] finished in {$ms}ms";
    }
};

echo $timer->summary(42) . "\n";

يمكن للصنف المجهول أن يرث من صنف أب عبر extends ويطبق واجهة أو أكثر عبر implements، مما يجعله مثالياً لبناء بدائل الاختبار السريعة (Mocks / Fakes).

  • اكتب new class implements MailerInterface { ... } لتلبية متطلبات أي واجهة برمجية بشكل فوري.
  • بما أن الكائن المجهول يطبق الواجهة، فإن الفحص $anon instanceof MailerInterface يُرجع true.
  • يتيح هذا النمط اختبار الخدمات في الذاكرة دون إرسال رسائل حقيقية أو الاتصال ببوابات دفع خارجية.

يطبق الصنف المجهول الواجهة AuditLogger ويحفظ الأحداث المسجلة في مصفوفة داخل الذاكرة للتحقق الفوري منها.

PHP
<?php
interface AuditLogger { public function record(string $event): void; }

$memoryLog = new class implements AuditLogger {
    public array $entries = [];
    public function record(string $event): void { $this->entries[] = $event; }
};
$memoryLog->record("user.login");
$memoryLog->record("order.paid");
echo implode(" -> ", $memoryLog->entries) . "\n";

على عكس json_encode() التي تفقد اسم صنف الكائن وخصائصه الخاصة، تحوّل الدالة serialize() الكائن إلى نص قابل للتخزين يحتفظ بنوع الصنف وحالة خصائصه كاملة.

  • ترمّز الدالة serialize($object) اسم الصنف وجميع الخصائص العامة والمحمية والخاصة في سلسلة نصية مهيكلة.
  • تعيد الدالة unserialize($payload) بناء الكائن الحي بنفس حالته دون إعادة استدعاء __construct().
  • تُستخدم هذه الآلية بكثرة لتخزين كائنات المهام الخلفية (Queued Jobs) في Redis أو قاعدة البيانات.

تحفظ serialize() كلاً من الخاصية العامة $task والخاصة $retries، وتستعيد unserialize() الكائن QueuedJob بالكامل.

PHP
<?php
class QueuedJob {
    public function __construct(public string $task, private int $retries) {}
    public function info(): string { return "{$this->task} (tries={$this->retries})"; }
}
$raw = serialize(new QueuedJob("SendInvoicePdf", 3));
$restored = unserialize($raw);
echo $restored->info() . "\n";

يوفر PHP 8 الدالتين السحريتين __serialize(): array و__unserialize(array $data): void للتحكم الدقيق في البيانات التي يتم حفظها واستعادتها.

  • تُرجع الدالة __serialize(): array مصفوفة ترابطية نظيفة تمثل حالة الكائن المراد حفظها (مع استبعاد المقابض الحية أو المفاتيح المؤقتة).
  • تستقبل الدالة __unserialize(array $data): void تلك المصفوفة الترابطية عند فك التسلسل لتعيد تعبئة خصائص الكائن.
  • فضّل دائماً الثنائي الحديث __serialize() و__unserialize() على الدالتين القديمتين __sleep() و__wakeup().

تستبعد __serialize() الخاصية المؤقتة $tempCache عند الحفظ، وتعيد __unserialize() تهيئتها بالقيمة "rebuilt".

مخطط تدفق التنفيذ العملي لقسم تخصيص البيانات المحفوظة عبر __serialize و __unserialize في لغة PHP
PHP
<?php
class SessionToken {
    public function __construct(public string $user, private string $tempCache = "skip") {}
    public function __serialize(): array { return ["user" => $this->user]; }
    public function __unserialize(array $data): void {
        $this->user = $data["user"];
        $this->tempCache = "rebuilt";
    }
    public function status(): string { return "{$this->user}:{$this->tempCache}"; }
}
$tok = unserialize(serialize(new SessionToken("admin")));
echo $tok->status() . "\n";

لا تمرر أبداً بيانات خارجية غير موثوقة إلى unserialize() دون تقييد الخيار allowed_classes، لمنع ثغرات حقن الكائنات (PHP Object Injection).

  • مرّر الخيار ['allowed_classes' => [SafeDto::class]] كمعامل ثانٍ للدالة unserialize() لحصر فك التسلسل في الأصناف المسموحة فقط.
  • مرّر ['allowed_classes' => false] لمنع إنشاء أي كائنات إطلاقاً، فيتحول أي كائن غير مصرح به إلى __PHP_Incomplete_Class غير قابل للتنفيذ.
  • عند تبادل البيانات مع المتصفح أو الكوكيز أو واجهات API الخارجية، استخدم json_encode() وjson_decode() بدلاً من serialize().

لأن الصنف DangerExec غير موجود في القائمة البيضاء allowed_classes، يرفض PHP إنشاءه ويحوله إلى __PHP_Incomplete_Class آمن.

PHP
<?php
class SafeCart { public string $sku = "KB-90"; }
class DangerExec { public string $cmd = "rm"; }

$payload = serialize(new DangerExec());
$res = unserialize($payload, ["allowed_classes" => [SafeCart::class]]);

echo get_debug_type($res) . "\n";

يوفر PHP المعامل instanceof ودوال فحص سريعة للتحقق من صنف الكائن وسلسلة وراثته والواجهات التي يطبقها وقت التشغيل.

  • يُرجع التعبير $obj instanceof TargetType القيمة true إذا كان الكائن من نفس الصنف أو يرث منه أو يطبق تلك الواجهة.
  • استخدم get_debug_type($val) (في PHP 8.0+) أو $obj::class لمعرفة اسم الصنف الفعلي للكائن وقت التشغيل.
  • استخدم method_exists($obj, 'name') وproperty_exists($obj, 'prop') لفحص وجود الدوال والخصائص برمجياً.

يتحقق الكود من تطبيق الواجهة عبر instanceof، ويقرأ اسم الصنف عبر $rep::class، ويؤكد وجود الدالة toCsv().

الأداة / الدالةالوظيفة الأساسيةمثال
$obj instanceof TypeChecks class, parent class, or interface match$r instanceof Exportable
$obj::classReturns exact class name string (PHP 8.0+)"SalesReport"
method_exists($o, $m)Checks if method is defined on object/classmethod_exists($r, "toCsv")
unserialize($s, $opts)Restores object with class whitelist["allowed_classes" => [Safe::class]]

PHP
<?php
interface Exportable { public function toCsv(): string; }
class SalesReport implements Exportable {
    public function toCsv(): string { return "id,total"; }
}
$rep = new SalesReport();
echo ($rep instanceof Exportable ? "Exportable" : "No") . " | ";
echo $rep::class . " | ";
echo (method_exists($rep, "toCsv") ? "has toCsv()" : "missing") . "\n";
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

يوفر PHP المعامل instanceof ودوال فحص سريعة للتحقق من صنف الكائن وسلسلة وراثته والواجهات التي يطبقها وقت التشغيل. يُرجع التعبير $obj instanceof TargetType القيمة true إذا كان الكائن من نفس الصنف أو يرث منه أو يطبق تلك الواجهة. استخدم get_debug_type($val) (في PHP 8.0+) أو $obj::class لمعرفة اسم الصنف الفعلي للكائن وقت التشغيل. استخدم method_exists($obj, 'name') وproperty_exists($obj, 'prop') لفحص وجود الدوال والخصائص برمجياً.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Anonymous & Serialize الأصناف المجهولة والتسلسل
أنشئ كائنات فورية عبر new class، وخزّن الكائنات بأمان عبر __serialize و__unserialize، وافحص الأصناف والدوال في وقت التشغيل.
للمراجعة
02 Creating Inline Objects with new class إنشاء الكائنات الفورية بالأصناف المجهولة new class
المفهوم الأساسي لقسم إنشاء الكائنات الفورية بالأصناف المجهولة new class في لغة PHP الحديثة.
للمراجعة
03 Implementing Interfaces in Anonymous Classes تطبيق الواجهات داخل الأصناف المجهولة للاختبار السريع
الصياغة البرمجية والتطبيق العملي المباشر لقسم تطبيق الواجهات داخل الأصناف المجهولة للاختبار السريع.
للمراجعة
04 Serializing Objects with serialize تحويل الكائنات إلى نص قابل للتخزين بـ serialize
قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم تحويل الكائنات إلى نص قابل للتخزين بـ serialize.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 PHP PHP
PHP: Hypertext Preprocessor
لغة البرمجة النصية على جانب الخادم لبناء تطبيقات الويب الديناميكية وواجهات البرمجة.
للمراجعة
02 CLI CLI
Command-Line Interface
واجهة سطر الأوامر التي تتيح تشغيل ملفات PHP مباشرة عبر الطرفية.
للمراجعة
03 FPM FPM
FastCGI Process Manager
مدير عمليات FastCGI عالي الأداء لمعالجة طلبات خادم الويب في PHP.
للمراجعة
04 HTML HTML
HyperText Markup Language
لغة الترميز القياسية التي يولدها محرك PHP ويرسلها إلى متصفح العميل بعد التنفيذ.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم إنشاء الكائنات الفورية بالأصناف المجهولة new class للتحقق من المخرجات.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم تطبيق الواجهات داخل الأصناف المجهولة للاختبار السريع وقارن مخرجات التنفيذ.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

8أسئلة 1أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي8 أسئلة تنتظرك
01

كيف تنشئ كائناً فورياً من صنف مجهول في PHP مع تمرير القيمة "v1" إلى دالة البناء الخاصة به؟

توضع معاملات البناء بين قوسين مباشرة بعد الكلمة new class(...).

02

هل يمكن للصنف المجهول في PHP أن يطبق واجهة (implements) أو يرث من صنف أب (extends)؟

تدعم الأصناف المجهولة كلاً من extends وimplements تماماً كالأصناف المسماة.

03

ما زوج الدوال السحرية الحديث في PHP 8 المخصص للتحكم في كيفية تسلسل الكائن وفك تسلسله؟

هما الدالتان القياسيتان الحديثتان في PHP 8 لتخصيص تسلسل الكائنات.

04

كيف تمنع ثغرات حقن الكائنات عند استدعاء unserialize() على نص يفترض أن يحتوي فقط على كائنات من الصنف OrderDto؟

يحدد الخيار allowed_classes قائمة بيضاء بالأصناف المسموح بإنشائها فقط.

05

ماذا تنتج الدالة unserialize($payload, ["allowed_classes" => false]) إذا كان النص يحتوي على كائن متسلسل؟

ضبط allowed_classes على false يمنع إنشاء أي صنف ويحول الكائنات إلى __PHP_Incomplete_Class آمن.

06

متى تُرجع العبارة ($obj instanceof Auditable) القيمة المنطقية true؟

يفحص المعامل instanceof الصنف المباشر وجميع الأصناف الأب والواجهات المطبقة.

07

في PHP 8.0+، كيف يمكنك الحصول على اسم الصنف الفعلي للكائن $service وقت التشغيل باستخدام صيغة ::class؟

يدعم PHP 8.0+ كتابة $object::class مباشرة على الكائن لإرجاع اسم صنفه النصي.

08

ما الدالة المدمجة في PHP التي تفحص ما إذا كان الكائن $plugin يحتوي على دالة معرفة باسم "boot"؟

تُرجع method_exists($plugin, "boot") القيمة true إذا كانت الدالة موجودة في الكائن.