با سلام، در قسمت قبل به طور کامل با دستور use و مبحث aliasing آشنا شدیم. در این قسمت به سراغ مباحث متعددی می رویم که اولین آن ها بحث Name resolution (تجزیه یا ترجمه ی نام ها) است.
قوانین Name resolution
زمانی که کد شما کامپایل می شود بسیاری از نام هایی که ما به صورت قرار دادی تعیین کرده ایم (مثل alias ها) تبدیل به نام های اصلی می شوند، به این فرآیند Name resolution می گوییم.
برای درک کردن این بحث باید با مفاهیم Unqualified name (مانند ()MyFunction) و Qualified name (مانند ()Lib1MyFunction) و Fully qualified name مانند (()AppLib2MyFunction) آشنا باشید.
اگر با این موارد آشنایی ندارید لطفا این فصل را مطالعه کنید:
البته یک نوع نامگذاری دیگر نیز وجود دارد که به آن Relative name می گوییم؛ در این نام گذاری namespace نیز ذکر می شود. مثال: namespaceFooBar
چند مورد از قوانین اصلی name resolution به این شرح هستند:
- علامت بک اسلش “” در نام های Fully qualified برداشته می شوند. به طور مثال AB تبدیل به AB می شود.
- نام های qualified و Unqualified با توجه به قوانین import (استفاده از دستور use) ترجمه می شوند. به طور مثال اگر namespace ای به آدرس ABC را با کلیدواژه ی
as به C تبدیل کرده باشیم، فراخوانی CDE به ABCDE تبدیل می شود؛ یعنی به نام کامل و صحیحش برمیگردد.
سعی می کنم این قوانین را که بیشتر از دو مورد بالا هستند در یک مثال توضیح دهم تا مطلب کاملا مفهوم شود. من تنها قوانین مهم و کاربردی را ذکر می کنم. می توانید دیگر قوانین را در صفحه ی رسمی مربوطه در سایت PHP ببینید.
تصور کنید در ابتدای فایل ما این کد وجود دارد:
| <?php namespace A; use BD, CE as F; |
با توجه به کد بالا صدا زدن توابع به این شکل اجرا می شود:
برای تابع ;()foo
- ابتدا سعی می کند تابع foo را در namespace ای به نام A پیدا کند (یعنی namespace اصلی فایل).
- اگر موفق نشود، سعی می کند تابع foo را در global namespace (فضای global) پیدا کند.
برای تابع ;()foo
سعی می کند این تابع را در فضای گلوبال پیدا کند.
برای تابع ;()myfoo
سعی می کند تابع foo را در namespace به آدرس Amy پیدا کند.
برای تابع ;()F
- سعی می کند F را در نیم اسپیسِ A پیدا کند.
- اگر موفق نشد، سعی می کند، تابع F را در فضای global پیدا کند.
ثابت __NAMESPACE__
این دستور همیشه نام namespace فعلی را به صورت یک رشته بر میگرداند:
| <?php namespace AppLib1; echo __NAMESPACE__; // outputs: AppLib1 ?> |
همانطور که در خود کد توضیح دادیم عبارت “AppLib1” را به ما برمیگرداند.
نکته: اگر کدهای ما در فضای global باشند، یک رشته ی خالی به ما برگردانده می شود.
جدا از مزایایی که این دستور در هنگام دیباگ کردن سیستم به ما می دهد، می توان از آن برای تولید نام برای کلاس ها به صورت fully qualified و پویا استفاده کرد:
| <?php namespace AppLib1; class MyClass { public function WhoAmI() { retu __METHOD__; } } $c = __NAMESPACE__ . '\MyClass'; $m = new $c; echo $m->WhoAmI(); // outputs: AppLib1MyClass::WhoAmI ?> |
کلیدواژه ی namespace
در اینجا منظور ما مفهوم namespace (به معنی فضای نام) نیست بلکه منظورمان یک دستور برنامه نویسی به نام namespace است! این دو را اشتباه نگیرید!
میتوانیم از دستور namespace برای اشاره ی مستقیم به یک namespace یا namespace های زیرین (nested شده ها و …) استفاده کنیم، بنابراین این دستور معادل همان دستور self در کلاس ها است.
اگر از دستور self در کلاس ها چیزی به خاطر ندارید به مقاله ی زیر مراجعه کنید:
مثال:
| <?php namespace AppLib1; class MyClass { public function WhoAmI() { retu __METHOD__; } } $m = new namespaceMyClass; echo $m->WhoAmI(); // outputs: AppLib1MyClass::WhoAmI ?> |
نکته: در خط دوم از کد بالا با کلمه ی namespace مواجه می شویم. این کلمه در اینجا برای تعریف کردن namespace ها است (همان چیزی که قبلا خوانده ایم). اما در خط های پایانی با دستور “new namespaceMyClass” مواجه می شویم. این همان دستوری است که به namespace فعلی اشاره دارد؛ اگر دقت کنید خروجی این کد نیز AppLib1 را به ما برگردانده است.
Autoload کردن کلاس های namespace
کلمه ی Autoload به معنی “بارگذاری خودکار” است. این ویژگی زبان PHP هیچ اختصاصی به namespace ها و غیر آن ندارد بلکه یک قابلیت همگانی در این زبان است. در حالت عادی و فضای global، توابع autoload به این شکل نوشته می شوند:
| <?php $obj1 = new MyClass1(); // classes/MyClass1.php is auto-loaded $obj2 = new MyClass2(); // classes/MyClass2.php is auto-loaded // autoload function function __autoload($class_name) { require_once("classes/$class_name.php"); } ?> |
اما از PHP 5.3 به بعد شما می توانید یک نمونه از یک کلاس namespace شده را بسازید. در چنین حالتی نام namespace و کلاس، به صورت fully qualified، به تابع autoload__ تحویل داده می شود.
به طور مثال، در کد بالا مقدار class_name$ می تواند AppLib1MyClass باشد. شما می توانید تمام فایل های کلاس هایتان را در یک فولدر قرار دهید و namespace را از رشته ی برگردانده شده حذف کنید اما این کار توصیه نمی شود چرا که ممکن است باعث تصادم نام فایل ها شود (فایل هایی با نام یکسان و در یک محل).
از طرفی نظام سلسه مراتبی در فایل های کلاس های شما، می توانند دارای ساختاری مشابه با ساختار namespace ها باشند؛ به طور مثال میتوانید فایل MyClass.php را در آدرس classes/App/Lib1/ قرار دهید. به مثال زیر توجه کنید:
محتویات classesAppLib1MyClass.php به این شکل است:
| <?php namespace AppLib1; class MyClass { public function WhoAmI() { retu __METHOD__; } } ?> |
حال، فایلی که در مسیر root (مسیر اصلی و ریشه ای) قرار دارد می تواند از کد زیر استفاده کند:
محتویات فایل myapp.php
| <?php use AppLib1MyClass as MC; $obj = new MC(); echo $obj->WhoAmI(); // autoload function function __autoload($class) { // به آدرس کامل فایل namespace تبدیل $class = 'classes' . str_replace('', '/', $class) . '.php'; require_once($class); } ?> |
نکات این کد:
- کلاس AppLib1MyClass به صورت MC خلاصه نویسی شده (مبحث aliasing از جلسه ی قبل)
- دستور
()new MC در هنگام کامپایل شدن کد، تبدیل به ()new AppLib1MyClass می شود. - دستور str_replace از این جهت استفاده شده است که تمام بک اسلش “” های namespace را به فوروارد اسلش “/” تبدیل کند. چرا؟ زیرا مسیر فایل ها همیشه با فوروارد اِسلَش کار می کند. بنابراین AppLib1MyClass تبدیل به classes/App/Lib1/MyClass.php شده و همین فایل نیز بارگذاری می شود.
خلاصه ی مقاله
در این قسمت با برخی مباحث جسته و گریخته از namespace ها آشنا شدیم که برخی از آن ها عبارت اند از name resolution (ترجمه یا تجزیه ی نام ها)، برخی کلمات کلیدی و دستورات مانند __NAMESPACE__ و مبحث autoload یا بارگذاری خودکار. امیدوارم از این قسمت لذت برده باشید.
برای دسترسی به تمام مقاله های پیرامون namespace ها در PHP لطفا روی این لینک کلیک کنید.
کارت ویزیت لایه باز...
ما را در سایت کارت ویزیت لایه باز دنبال میکنید
برچسب: نویسنده: بازدید: 175 تاريخ: سه شنبه 30 بهمن 1397 ساعت: 8:44