التحميل التلقائي للأصناف في PHP

من موسوعة حسوب
< PHP

يُنشئ أغلب المطوّرين الذي يكتبون تطبيقات كائنية التوجه ملف PHP واحد لكل صنف. وهنا تظهر مشكلة مزعجة للغاية، وهي الحاجة إلى كتابة قائمة طويلة بالأصناف التي يجب تضمينها للبدء بتنفيذ الشيفرة (قائمة لكل صنف).

لم يعد هذا الأمر ضروريًا في الإصدار الخامس من اللغة، إذ تسجّل الدالة spl_autoload_register()‎‎ عددًا غير محدّدٍ من المحمّلات التلقائية لتتيح إمكانية التحميل التلقائي للأصناف والواجهات غير المعرّفة في ملف الشيفرة. يمنح تسجيلُ المحمّلات التلقائية اللغةَ فرصة أخيرة لتحميل الصنف أو الواجهة قبل أن تتوقف الشيفرة عن العمل وتطلق خطأً.

نصيحة: يمكن استخدام الدالة ‎__autoload()‎ أيضًا لتحميل الأصناف والواجهات تلقائيًا، ولكن يفضّل استخدام الدالة spl_autoload_register()‎. والسبب هو أنّ الدالة الأخيرة أكثر مرونة (تسمح بتعيين عدد غير محدّد من المحمّلات التلقائية في التطبيق، كما في مكتبات الطرف الثالث)؛ ولهذا لا ينصح باستخدام الدالة ‎__autoload()‎ وقد تصبح مهملة في المستقبل.

ملاحظة: قبل الإصدار 5.3 من اللغة، لم يكن بالإمكان التقاط الاستثناءات التي تطلقها الدالة __autoload() بواسطة كتلة catch وقد يتسبب الأمر في حدوث خطأ من نوع fatal. ولكن في الإصدار 5.3 وما بعده، أصبح هذا الأمر ممكنًا بشرط إطلاق استثناء المخصص، ثم يكون صنف الاستثناء المخصص متاحًا. يمكن استخدام الدالة ‎__autoload()‎ تعاوديًا لتحميل صنف الاستثناء المخصص تلقائيًا.

ملاحظة: التحميل التلقائي غير متاحٍ عند استخدام PHP في نمط سطر الأوامر التفاعلي CLI.

ملاحظة: يمكن لاسم الصنف أن يتضمّن بعض المحارف الخطيرة مثل ‎../.‎ إن استُخدم على سبيل المثال في الدالة call_user_func()‎؛ لذا ينصح بعدم استخدام مدخلات المستخدم في مثل هذه الدوال أو التحقّق على الأقل من المدخلات في الدالة ‎__autoload()‎.

المثال 1: مثال على التحميل التلقائي

تحاول الشيفرة التالية تحميل الصنفين MyClass1 و MyClass2 من الملفين MyClass1.php و MyClass2.php على التوالي.

<?php
spl_autoload_register(function ($class_name) {
    include $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2(); 
?>

المثال 2: مثال آخر على التحميل التلقائي

تحاول هذه الشيفرة تحميل الواجهة ITest.

<?php

spl_autoload_register(function ($name) {
    var_dump($name);
});

class Foo implements ITest {
}

/*
string(5) "ITest"

Fatal error: Interface 'ITest' not found in ...
*/
?>

المثال 3: التحميل التلقائي مع التحكم في الاستثناءات في الإصدار 5.3.0 وما بعده من اللغة

ترمي الشيفرة التالية استثناءً وتبيّن طريقة استخدام كتلة try/catch.

<?php
spl_autoload_register(function ($name) {
    echo "Want to load $name.\n";
    throw new Exception("Unable to load $name.");
});

try {
    $obj = new NonLoadableClass();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
?>

تعطي الشيفرة السابقة النتائج التالية:

Want to load NonLoadableClass.
Unable to load NonLoadableClass.

المثال 4: التحميل التلقائي مع معالجة الاستثناءات في الإصدار 5.3.0 وما بعده من اللغة مع وجود استثناء مخصّص

ترمي الشيفرة التالية استثناء مخصصًا عندما يكون الصنف غير قابلٍ للتحميل.

<?php
spl_autoload_register(function ($name) {
    echo "Want to load $name.\n";
    throw new MissingException("Unable to load $name.");
});

try {
    $obj = new NonLoadableClass();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
?>

تعطي الشيفرة السابقة النتائج التالية:

Want to load NonLoadableClass.
Want to load MissingException.

Fatal error: Class 'MissingException' not found in testMissingException.php on line 4

انظر أيضًا

  • الدالة unserialize()‎ : إعطاء قيمة بلغة PHP انطلاقًا من تمثيل مُخزَّن.
  • الدالة unserialize_callback_func‎ : دالة استدعاء عند استنساخ صنف غير مُعرَّف خلال فك التسلسل.
  • الدالة spl_autoload_register()‎ : تحميل الأصناف والواجهات تلقائيًا.
  • الدالة spl_autoload()‎ : تحميل الأصناف والواجهات تلقائيًا.
  • الدالة ‎__autoload()‎‎ : تحميل الأصناف والواجهات تلقائيًا.

مصادر