يضع فضاء الأسماء في PHP الأصناف والدوال والثوابت تحت بادئة حتى لا تتعارض أسماؤها مع أسماء غيرك. تصرّح به بـ namespace App\Models; جملةً أولى في الملف، وتشير الملفات الأخرى إلى الصنف بـ \App\Models\User، أو تستورده بـ use App\Models\User; وتكتب User فقط.
داخل فضاء الأسماء، يعني User الاسم App\Models\User. وتعطي User::class الاسم الكامل نصًا دون إنشاء أي شيء، وهذا مفيد للتسجيل وللمحمّلات التلقائية.
فضاءا أسماء في ملف واحد
يضع المشروع الحقيقي فضاء أسماء واحدًا في كل ملف. ولعرض مستقل، يمكن لملف واحد أن يحمل عدة فضاءات أسماء عندما يُحاط كل منها بأقواس معقوصة. والشيفرة التي لا تنتمي إلى أي فضاء أسماء توضع في namespace { }:
يعيش صنفان اسمهما Order جنبًا إلى جنب لأن اسميهما الكاملين مختلفان. وهذه بالضبط المشكلة التي تحلها فضاءات الأسماء حين تثبّت مكتبات: لم يعد Order الخاص بك وOrder في مكتبة الدفع وOrder في مكتبة PDF تتعارض.
الاستيراد بـ use والتسمية البديلة بـ as
كتابة \Shop\Order في كل مكان مزعجة. تستورد use في أعلى الملف (أو كتلة فضاء الأسماء) اسمًا فتستخدم الصيغة القصيرة. وعندما ينتهي استيرادان بالاسم القصير نفسه، تعطي as أحدهما اسمًا مختلفًا:
لا تنشئ use إلا اسمًا قصيرًا لبقية الملف. لا تحمّل ملفًا ولا تشغّل شيفرة، وتعمل بالطريقة نفسها سواء وُجد الصنف بعد أم لا. والاستيراد المجمّع مسموح أيضًا: use Shop\{Order, Invoice};.
use function وuse const
تُستورد الدوال والثوابت في فضاء أسماء بـ use function وuse const:
الأصناف العامة تحتاج إلى شرطة مائلة عكسية
داخل فضاء أسماء، يُحل اسم الصنف غير المؤهل نسبةً إلى ذلك الفضاء، فتبحث new DateTime() داخل namespace App; عن App\DateTime. والدوال والثوابت مختلفة: إذا لم توجد App\strlen، ترجع PHP إلى strlen العامة. أما الأصناف فلا ترجع أبدًا.
احتاجت catch (\Error $e) إلى شرطة مائلة عكسية للسبب نفسه: من دونها ستبحث PHP عن App\Error، فلا تطابق الخطأ الحقيقي أبدًا، ويتوقف السكربت بـ Error غير ملتقط. أصلحه إما بشرطة مائلة عكسية بادئة، كما في الأعلى، أو بـ use DateTime; في أعلى الملف. وينطبق الأمر نفسه على \Exception و\Throwable وكل صنف مدمج آخر؛ راجع try catch لالتقاطها.
التحميل التلقائي وPSR-4
في المشروع، يعيش كل صنف في ملفه الخاص، ويتبع مسار الملف فضاء الأسماء. PSR-4 هو الاصطلاح: تقابل بادئة فضاء الأسماء مجلدًا أساسيًا، ويصبح بقية الاسم المسار. عندها يحمّل محمّل تلقائي مسجّل بـ spl_autoload_register() ملف الصنف أول مرة يُستخدم فيها الصنف. تكتب هذه الكتلة ملفي صنفين على القرص وتحمّلهما تلقائيًا:
يُحمَّل كل ملف صنف مرة واحدة، لحظة الحاجة إلى الصنف أول مرة. وفي المشاريع الحقيقية لا تكتب هذه الدالة بنفسك: يولّدها Composer من بضعة أسطر في composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
بعد composer dump-autoload، يحمّل سطر require __DIR__ . '/vendor/autoload.php'; واحد في بداية سكربت الدخول كل صنف App\... عند الطلب.
قواعد فضاءات الأسماء التي تسبب أخطاء
- يجب أن تكون
namespaceالجملة الأولى في الملف. ولا يجوز أن يسبقها إلاdeclare(strict_types=1);والتعليقات. - عبارات
useخاصة بكل ملف. استيراد صنف فيindex.phpلا يجعل الاسم القصير يعمل داخل ملف مُضمَّن؛ يحتاج كل ملف إلى أسطرuseالخاصة به. - مكان
useهو المستوى الأعلى من الملف أو كتلة فضاء الأسماء. وداخل جسم صنف، تعنيuseشيئًا آخر: تجلب سمة. - النصوص لا تُحل أبدًا: تبحث
$class = 'User'; new $class();عنUserالعام. خزّن الاسم الكامل، ويُفضّل بـUser::class.
القاعدة الأخيرة تستحق فحصًا سريعًا:
الأسئلة الشائعة
ما هو فضاء الأسماء في PHP؟
بادئة تجمع الأصناف والواجهات والدوال والثوابت المترابطة، مثل مجلد للأسماء. تضع namespace App\Models; في أعلى ملف صنفه User في App\Models\User، فلا يمكن أن يتعارض مع User من مكتبة أخرى.
ماذا تفعل use في PHP؟
تتيح لك use App\Models\User; في أعلى ملف أن تكتب User بدل الاسم الكامل \App\Models\User في ذلك الملف. ولا تحمّل ولا تضمّن أي شيء؛ فتحميل ملف الصنف مهمة المحمّل التلقائي. وتختار use ... as Alias; اسمًا قصيرًا مختلفًا.
لماذا أحصل على Class not found داخل فضاء أسماء؟
داخل namespace App; يُحل اسم الصنف المجرد نسبةً إلى فضاء الأسماء، فتبحث new DateTime() عن App\DateTime. اكتب new \DateTime() أو أضف use DateTime; في الأعلى. أما الدوال والثوابت فترجع إلى فضاء الأسماء العام تلقائيًا، والأصناف لا.
ما هي الشرطة المائلة العكسية قبل اسم الصنف في PHP؟
الشرطة المائلة العكسية البادئة تجعل الاسم مؤهلًا كليًا، يبدأ من فضاء الأسماء العام: \Exception هو دائمًا Exception المدمج في PHP، أيًّا كان فضاء الأسماء الذي فيه الشيفرة. ودونها يُحل الاسم نسبةً إلى فضاء الأسماء الحالي وعبارات use.
ما علاقة فضاءات الأسماء بالمجلدات وPSR-4؟
لا تربط PHP نفسها فضاءات الأسماء بالمجلدات. PSR-4 هو الاصطلاح الذي يفعل ذلك: بادئة مثل App\ تقابل مجلدًا مثل src/، فيعيش App\Models\User في src/Models/User.php. ويتبعه المحمّل التلقائي في Composer، ولهذا يتطابق الاثنان عادة.