تمت إضافة مساحة الاسم PHP (مساحة الاسم) في PHP 5.3. إذا كنت قد درست C# وJava، فإن مساحة الاسم ليست جديدة. ومع ذلك، لا يزال له أهمية كبيرة في لغة PHP.
يمكن لمساحات أسماء PHP حل النوعين التاليين من المشاكل:
تتعارض الأسماء بين التعليمات البرمجية التي كتبها المستخدم والفئات/الوظائف/الثوابت الداخلية لـ PHP أو الفئات/الوظائف/الثوابت التابعة لجهات خارجية.
قم بإنشاء اسم مستعار (أو قصير) لاسم معرف طويل جدًا (يتم تعريفه عادةً لتخفيف النوع الأول من المشكلة) لتحسين إمكانية قراءة التعليمات البرمجية المصدر.
افتراضيًا، يتم وضع جميع أسماء الثوابت والفئات والوظائف في المساحة العامة، تمامًا كما كان الحال قبل مساحات الأسماء المدعومة بواسطة PHP.
يتم الإعلان عن مساحات الأسماء باستخدام مساحة الاسم الأساسية. إذا كان الملف يحتوي على مساحة اسم، فيجب أن يعلن عن مساحة الاسم قبل كل التعليمات البرمجية الأخرى. تنسيق بناء الجملة كما يلي؛
<?php // تحديد الكود في مساحة الاسم "MyProject" MyProject;
يمكنك أيضًا تحديد رموز مساحة اسم مختلفة في نفس الملف، مثل:
<?php namespace MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }functionconnect() { /* ... */ }namespace AnotherProject;const CONNECT_OK = 1;class Connection { /* .. .*/ }functionconnect() { /* ... */ }?>
لا يوصى باستخدام بناء الجملة هذا لتعريف مساحات أسماء متعددة في ملف واحد. من المستحسن استخدام نموذج القوس المتعرج التالي لبناء الجملة.
<?phpnamespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } functionconnect() { /* ... */ }}namespace AnotherProject { const CONNECT_OK = 1; */ } وظيفة الاتصال() { /* ... */ }}?>
لدمج التعليمات البرمجية العامة التي لا تتعلق بمساحة الاسم مع رمز مساحة الاسم، يمكن استخدام بناء جملة القوس المتعرج فقط. يجب أن يتم تضمين الكود العام في عبارة مساحة اسم غير مسماة متبوعة بأقواس، على سبيل المثال:
<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }functionconnect() { /* ... */ }}namespace { // Global code session_start();$a = MyProject Connect();echo MyProjectConnection::start();}?>
الكود القانوني الوحيد قبل الإعلان عن مساحة الاسم هو عبارة التصريح التي تحدد ترميز الملف المصدر. لا يمكن أن تظهر كافة التعليمات البرمجية غير PHP، بما في ذلك المسافات البيضاء، قبل إعلان مساحة الاسم.
<?phpdeclare(encoding='UTF-8'); // تحديد مساحات أسماء متعددة ومساحات أسماء التعليمات البرمجية غير المضمنة في مساحة الاسم MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }functionconnect () { / * ... */ }}namespace { // الكود العام session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
سوف يسبب التعليمة البرمجية التالية خطأ في بناء الجملة:
<html><?phpnamespace MyProject; // ظهور "<html>" قبل مساحة الاسم سيؤدي إلى خطأ فادح - يجب أن تكون مساحة الاسم هي العبارة الأولى للبرنامج النصي؟>
تمامًا مثل العلاقة بين الدلائل والملفات، تتيح لك مساحات الأسماء PHP أيضًا تحديد أسماء مساحات الأسماء الهرمية. لذلك، يمكن تعريف أسماء مساحة الاسم بطريقة هرمية:
<?phpnamespace MyProjectSubLevel; // أعلن عن مساحة اسم مفردة هرمية const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
ينشئ المثال أعلاه الثابت MyProjectSubLevelCONNECT_OK والفئة MyProjectSubLevelConnection والدالة MyProjectSubLevelConnect.
يمكن الرجوع إلى أسماء الفئات في مساحة اسم PHP بثلاث طرق:
اسم غير مؤهل، أو اسم فئة بدون بادئة، مثل $a=new foo(); أو foo::staticmethod();. إذا كانت مساحة الاسم الحالية هي مساحة الاسم الحالية، فسيتم حل foo إلى مساحة الاسم الحاليةfoo. إذا كانت التعليمات البرمجية التي تستخدم foo عمومية ولا تحتوي على تعليمات برمجية في أي مساحة اسم، فسيتم حل foo على أنها foo. تحذير: إذا كانت الوظيفة أو الثابت في مساحة الاسم غير محددة، فسيتم تحويل الوظيفة غير المؤهلة أو الاسم الثابت إلى دالة عامة أو اسم ثابت.
اسم مؤهل، أو اسم يتضمن بادئة، مثل $a = new subnamespacefoo(); أو subnamespacefoo::staticmethod();. إذا كانت مساحة الاسم الحالية هي مساحة الاسم الحالية، فسيتم حل foo إلى currentnamespacesubnamespacefoo. إذا كان الكود الذي يستخدم foo عامًا، والكود غير موجود في أي مساحة اسم، فسيتم تحليل foo إلى subnamespacefoo.
اسم مؤهل بالكامل، أو اسم يتضمن عامل تشغيل بادئة عمومي، على سبيل المثال، $a = new currentnamespacefoo(); أو currentnamespacefoo::staticmethod();. في هذه الحالة، يتم دائمًا تحويل foo إلى الاسم الحرفي currentnamespacefoo في الكود.
فيما يلي مثال على استخدام هذه الطرق الثلاثة:
رمز الملف file1.php
<?phpnamespace FooBarsubnamespace; const FOO = 1;function foo() {}class foo{ static function staticmethod() {}}?>
رمز الملف file2.php
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* اسم غير مؤهل*/foo(); هي الوظيفة FooBarfoofoo::staticmethod(); // يتم تحليلها في الفئة FooBarfoo والطريقة هي staticmethodecho FOO //; يحل محل FooBarFOO/* اسم مؤهل*/subnamespacefoo(); // يحل محل الوظيفة FooBarsubnamespacefoosubnamespacefoo::staticmethod(); foo، // وطرق الفصل staticmethodecho subnamespaceFOO // تم تحليلها إلى الثابت FooBarsubnamespaceFOO /* الاسم المؤهل بالكامل */FooBarfoo(); // يحل الوظيفة FooBarfooFooBarfoo::staticmethod(); // يحل مع الفئة FooBarfoo والفئة الطريقة staticmethodecho FooBarFOO // تم الحل كثابت FooBarFOO?>
لاحظ أنه للوصول إلى أي فئة عامة أو دالة أو ثابت، يمكنك استخدام اسم مؤهل بالكامل، مثل strlen() أو Exception أو INI_ALL.
الوصول إلى الفئات العامة والوظائف والثوابت داخل مساحة الاسم:
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // استدعاء الوظيفة العامة strlen$b = INI_ALL; c = new Exception('error'); // إنشاء مثيل لاستثناء الفئة العامة؟>
يتأثر تنفيذ مساحات أسماء PHP بالطبيعة الديناميكية للغة نفسها. لذلك، إذا كنت تريد تحويل التعليمات البرمجية أدناه إلى مساحة اسم، فقم بالوصول إلى العناصر ديناميكيًا.
رمز الملف example1.php:
<?phpclass classname{ function __construct() { echo __METHOD__,"n" }}function funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'classname';$obj = new $a; // يطبع اسم الفئة::__construct$b = 'funcname';$b(); // يطبع funcnameecho ثابت ('constname')، "n"؛ // يطبع بشكل عام؟>
يجب عليك استخدام اسم مؤهل بالكامل (اسم الفئة بما في ذلك بادئة مساحة الاسم). لاحظ أن الشرطة المائلة العكسية البادئة غير ضرورية لأنه لا يوجد فرق بين الأسماء المؤهلة والمؤهلة بالكامل في أسماء الفئات الديناميكية أو أسماء الوظائف أو الأسماء الثابتة.
الوصول ديناميكيًا إلى عناصر مساحة الاسم
<?phpnamespace namespacename;classname{ function __construct() { echo __METHOD__,"n" }}function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php' ;$a = 'classname';$obj = new $a; // اسم فئة الإخراج::__construct$b = 'funcname';$b(); // اسم وظيفة الإخراج echo Constant('constname'), "n"; // الإخراج العمومي/* إذا تم استخدام علامات الاقتباس المزدوجة، فإن طريقة الاستخدام هي "\namespacename\classname "* /$a = 'namespacenameclassname';$obj = new $a; // إخراج namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = new $a; // اسم مساحة الإخراجclassname::__construct$b = 'namespacenamefuncname';$b(); // اسم مساحة الإخراجfuncname$b = 'namespacenamefuncname';$b(); 'namespacenameconstname')، "n"; مساحة الاسم الإخراج؟>
تدعم PHP طريقتين مجردتين للوصول إلى العناصر الموجودة في مساحة الاسم الحالية، الثابت السحري __NAMESPACE__ والكلمة الأساسية لمساحة الاسم.
قيمة الثابت __NAMESPACE__ عبارة عن سلسلة تحتوي على اسم مساحة الاسم الحالية. في الكود العام، غير المضمن في أي مساحة اسم، يحتوي على سلسلة فارغة.
__NAMESPACE__ مثال، رمز في مساحة الاسم
<?phpnamespace MyProject;echo '"', __NAMESPACE__, '"'; // إخراج "MyProject"?>
__NAMESPACE__ مثال، الكود العام
<?phpecho '"', __NAMESPACE__, '"'; // الإخراج ""?>
يعد الثابت __NAMESPACE__ مفيدًا عند إنشاء الأسماء ديناميكيًا، على سبيل المثال:
إنشاء الأسماء ديناميكيًا باستخدام __NAMESPACE__
<?phpnamespace MyProject;function get($classname){ $a = __NAMESPACE__ '\'
يمكن استخدام مساحة اسم الكلمة الأساسية للوصول بشكل صريح إلى العناصر الموجودة في مساحة الاسم الحالية أو مساحات الأسماء الفرعية. وهو يعادل العامل الذاتي في الفصول الدراسية.
مشغل مساحة الاسم، رمز في مساحة الاسم
<?phpnamespace MyProject;use blahblah as my; // راجع "استخدام مساحات الأسماء: import/aliasing"blahmine(); وظيفة الاستدعاء MyProjectblahmine()namespacefunc(); // وظيفة الاستدعاء MyProjectfunc()namespacesubfunc(); MyProjectsubfunc()namespacecname::method(); // يستدعي "طريقة" الطريقة الثابتة للفئة MyProjectcname$a = new namespacesubcname(); // إنشاء كائن من الفئة MyProjectsub cname$b = namespaceCONSTANT; // يعين قيمة الثابت MyProjectCONSTANT إلى $b?>
مشغل مساحة الاسم، الكود العالمي
<?phpnamespacefunc(); // يستدعي الدالة func()namespacesubfunc(); // يستدعي الدالة subfunc()namespacecname::method(); class cname$a = new namespacesubcname(); // إنشاء كائن من الفئة subcname$b = namespaceCONSTANT;
يحتوي دعم مساحة الاسم PHP على طريقتين لاستخدام الأسماء المستعارة أو عمليات الاستيراد: استخدام الأسماء المستعارة لأسماء الفئات، أو استخدام الأسماء المستعارة لأسماء مساحة الاسم.
في PHP، يتم تنفيذ الاسم المستعار من خلال عامل الاستخدام فيما يلي مثال باستخدام طرق الاستيراد الثلاثة الممكنة:
1. استخدم عامل التشغيل لاستيراد/استخدام الأسماء المستعارة
<?phpnamespace foo;use MyFullClassname كآخر;// المثال التالي هو نفس استخدام MyFullNSname كـ NSname use MyFullNSname;// استيراد فئة عامة use ArrayObject;$obj = new namespaceAnother; // إنشاء كائن fooAnother $obj = new Another; استدعاء الوظيفة MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // إنشاء كائن ArrayObject // إذا لم تستخدم "استخدام ArrayObject"، فقم بإنشاء كائن fooArrayObject؟ >
2. يحتوي سطر واحد على بيانات استخدام متعددة
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // إنشاء كائن MyFullClassname NSnamesubnsfunc(); // استدعاء الدالة MyFullNSname subnsfunc؟>
يتم تنفيذ عمليات الاستيراد أثناء الترجمة، ولكن لا يتم تنفيذ أسماء الفئات الديناميكية أو أسماء الوظائف أو الأسماء الثابتة.
3. استيراد وأسماء ديناميكية
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // إنشاء كائن MyFullClassname $a = 'Another';$obj = new $a; كائن آخر؟>
بالإضافة إلى ذلك، تؤثر عملية الاستيراد على الأسماء المؤهلة وغير المؤهلة فقط. الأسماء المؤهلة بالكامل لا تتأثر بالواردات لأنها حتمية.
4. استيراد وأسماء مؤهلة بالكامل
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // إنشاء فئة MyFullClassname $obj = new Another; // إنشاء فئة أخرى $obj = new Another thing; // إنشاء فئة MyFullClassnamething $obj = new Anotherthing;
داخل مساحة الاسم، عندما تواجه PHP فئة أو وظيفة أو اسمًا ثابتًا غير مؤهل، فإنها تستخدم استراتيجية أسبقية مختلفة لحل الاسم. يتم دائمًا تحليل أسماء الفئات إلى الأسماء الموجودة في مساحة الاسم الحالية. لذلك، عند الوصول إلى أسماء الفئات الداخلية للنظام أو غير الموجودة في مساحة الاسم، يجب عليك استخدام الاسم المؤهل بالكامل، على سبيل المثال:
1. الوصول إلى الفئات العامة في مساحة الاسم
<?phpnamespace ABC;class Exception Extends Exception {}$a = new Exception('hi'); // $a كائن من الفئة ABCException $b = new Exception( 'hi'); // $b هو كائن من الفئة Exception $c = new ArrayObject; // خطأ فادح، لم يتم العثور على الفئة ABCArrayObject؟>
بالنسبة للوظائف والثوابت، إذا كانت الوظيفة أو الثابت غير موجود في مساحة الاسم الحالية، فستعود PHP إلى استخدام الوظيفة أو الثابت في المساحة العامة.
2. النسخ الاحتياطي للوظائف/الثوابت العالمية في مساحة الاسم
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n"; // الإخراج "45"echo INI_ALL, " n"; // الإخراج "7" - استخدم الثابت العام INI_ALLecho strlen('hi'), "n"; // الإخراج "2"if (is_array('hi')) { // الإخراج "ليس مصفوفة" echo "is arrayn";} else { echo "ليس مصفوفةn";}?>
إذا لم يتم تعريف أي مساحة اسم، فسيتم تعريف جميع الفئات والوظائف في المساحة العامة، تمامًا كما كان الحال قبل تقديم PHP لمفهوم مساحة الاسم. تشير إضافة الاسم بـ إلى أن الاسم موجود في المساحة العامة، حتى لو كان الاسم في مساحة اسم أخرى.
استخدم تعليمات الفضاء العالمية
<?phpnamespace ABC;/* هذه الوظيفة هي ABCfopen */function fopen() { /* ... */ $f = fopen(...); تقوم الدالة fopen بإرجاع $f;} ?>
منذ تقديم مساحات الأسماء، أصبح الشيء الأكثر عرضة للخطأ هو عند استخدام فئة ما، ما هو مسار البحث عن هذه الفئة.
<?phpnamespace A;use BD, CE كـ F;// استدعاء الدالة foo(); // حاول أولاً استدعاء الوظيفة foo() المحددة في مساحة الاسم "A" // ثم حاول استدعاء global function" foo"foo(); // استدعاء وظيفة المساحة العامة "foo" myfoo(); // استدعاء الوظيفة "foo" المحددة في مساحة الاسم "Amy" F(); حاول أولاً استدعاء الوظيفة "F" المحددة في مساحة الاسم "A" // ثم حاول استدعاء الوظيفة العامة "F" // مرجع الفئة new B(); // إنشاء فئة "B" محددة في مساحة الاسم "A" كائن of class "AB" new D(); // إذا لم يتم العثور عليه، فحاول التحميل التلقائي للفئة "AB" new D(); " // إذا لم يتم العثور عليه، حاول تحميل الفئة "BD" تلقائيًا F(); // باستخدام قواعد الاستيراد، أنشئ كائنًا من الفئة "E" محددًا في مساحة الاسم "C" // إذا لم يتم العثور عليه، فحاول التحميل التلقائي للفئة "CE" new B(); من الفئة "B" المحددة في الفضاء العالمي // إذا لم يتم العثور عليها، فحاول التحميل التلقائي للفئة "B" new D(); // أنشئ كائنًا من الفئة "D" محددًا في الفضاء العام // إذا لم يتم العثور عليه، فحاول ذلك فئة التحميل التلقائي "D" جديدة F(); // أنشئ كائنًا من الفئة "F" محددًا في المساحة العامة // إذا لم يتم العثور عليه، فحاول التحميل التلقائي للفئة "F" // استدعاء أسلوب ثابت أو وظيفة مساحة اسم في مساحة اسم أخرى Bfoo(); ; // استدعاء الدالة "foo" في مساحة الاسم "AB" B::foo(); // طريقة الاتصال "foo" للفئة "B" المحددة في مساحة الاسم "A" // إذا كانت الفئة "AB". لم يتم العثور عليه ، ثم حاول تحميل الفئة "AB" تلقائيًا D::foo(); // استخدم قواعد الاستيراد لاستدعاء طريقة "foo" للفئة "D" المحددة في مساحة الاسم "B" // إذا كانت الفئة "BD" " " إذا لم يتم العثور عليه، فحاول تحميل الفئة "BD"Bfoo(); // استدعاء الوظيفة "foo" في مساحة الاسم "B" B::foo(); وظيفة في فئة الفضاء العالمية "ب" الطريقة "foo" // إذا لم يتم العثور على الفئة "B"، فحاول التحميل التلقائي للفئة "B" // طريقة ثابتة أو وظيفة في مساحة الاسم الحالية AB::foo(); // استدعاء مساحة الاسم "A" طريقة "foo" للفئة "B" المحددة في A" // إذا لم يتم العثور على الفئة "AAB"، فحاول التحميل التلقائي للفئة "AAB"AB::foo() ; // استدعاء الأسلوب "foo" للفئة "B" المحددة في مساحة الاسم "A" // إذا لم يتم العثور على الفئة "AB"، فحاول تحميل الفئة "AB" تلقائيًا؟>
يتبع تحليل الاسم القواعد التالية:
يتم حل الاستدعاءات للأسماء المؤهلة بالكامل للوظائف والفئات والثوابت في وقت الترجمة. على سبيل المثال، يتحول AB الجديد إلى الفئة AB .
يتم تحويل كافة الأسماء غير المؤهلة والأسماء المؤهلة (غير المؤهلة بالكامل) في وقت الترجمة وفقًا لقواعد الاستيراد الحالية. على سبيل المثال، إذا تم استيراد مساحة الاسم ABC كـ C ، فستتم ترجمة الاستدعاءات إلى CDe() إلى ABCDe() .
ضمن مساحة الاسم، كافة الأسماء المؤهلة التي لم يتم تحويلها وفقًا لقواعد الاستيراد سيكون لها اسم مساحة الاسم الحالي مُلحقًا بها. على سبيل المثال، إذا تم استدعاء CDe() داخل مساحة الاسم AB ، فسيتم تحويل CDe() إلى ABCDe() .
يتم تحويل أسماء الفئات غير المؤهلة في وقت الترجمة وفقًا لقواعد الاستيراد الحالية (يتم استخدام الأسماء الكاملة بدلاً من أسماء الاستيراد القصيرة). على سبيل المثال، إذا تم استيراد مساحة الاسم ABC كـ C، فسيتم تحويل C() الجديد إلى ABC() الجديد .
ضمن مساحة الاسم (مثل AB)، يتم حل استدعاءات الوظائف للأسماء غير المؤهلة في وقت التشغيل. على سبيل المثال، يتم تحليل استدعاء الدالة foo() على النحو التالي:
ابحث عن دالة اسمها ABfoo() في مساحة الاسم الحالية
حاول العثور على الدالة foo() واستدعائها في الفضاء العالمي .
يتم حل الاستدعاءات للأسماء غير المؤهلة أو فئات الأسماء المؤهلة (الأسماء غير المؤهلة بالكامل) داخل مساحة الاسم (مثل AB ) في وقت التشغيل. فيما يلي عملية التحليل لاستدعاء C() الجديد و DE() الجديد : تحليل C() الجديد :
ابحث عن الفئات ABC في مساحة الاسم الحالية.
حاول التحميل التلقائي للفئات ABC .
تحليل DE() الجديد :ألحق اسم الفئة مع اسم مساحة الاسم الحالي ليصبح: ABDE ثم ابحث عن تلك الفئة.
حاول التحميل التلقائي للفئة ABDE .
للإشارة إلى فئة عمومية في مساحة الاسم العمومية، يجب استخدام الاسم المؤهل بالكامل new C() .