Namespace در PHP چیست؟

Namespaces in PHP

namespaces-in-php-2

با سلام، بنا به درخواست شما عزیزان قصد داریم به سراغ مبحث namespace ها در برنامه نویسی شیء گرای PHP برویم.

پیش نیاز: برای همراهی با این مقاله باید دانش قابل قبولی نسبت به برنامه نویسی شیء گرای PHP داشته باشید. اگر با برنامه نویسی شیء گرا آشنا نیستید می توانید از دوره آموزشی برنامه نویسی شیء گرای PHP استفاده کنید.

namespace چیست؟

اولین سوالی که در این زمینه برای ما پیش می آید این است که namespace چیست و چرا باید از آن ها استفاده کنیم. اجازه بدهید سوالتان را جواب بدهم:

همانطور که در برنامه نویسی پیشرفت می کنید و کدهای خصوصی خودتان را می نویسید، این کدها را روی هم انباشته می کنید. در برخی اوقات نیز برخی از پروژه ها آنقدر بزرگ هستند که حجم کدها در آن ها بسیار بالا می رود. کار کردن در این حجم از کد از نقطه نظر خاصی، سخت تلقی می شود و آن، حفظ کردن تمام نام هایی است که روی توابع، کلاس ها و ... گذاشته اید.

همانطور که می دانید زمانی که نامی را روی یک کلاس یا تابع می گذارید دیگر نمی توانید آن نام را روی تابع یا کلاس دیگری قرار دهید؛ در صورتی که چنین کاری انجام دهید به خطا برخورد خواهید کرد.

باید اعتراف کرد که به یاد داشتن نام توابع، کلاس ها، ثابت ها و انواع کدهایی که نوشته ایم کار سختی است.

حال پلاگین ها و کتابخانه ها را نیز به این وضعیتِ در هم ریخته اضافه کنید! باید هم مراقب کدهای خود باشیم، هم مراقب کلاس ها، توابع و... رزرو شده در خودِ PHP و هم مراقب کدهایی که در یک کتابخانه یا پلاگین استفاده شده اند!

namespace ها در واقع روشی برای کپسوله سازی (encapsulation) هستند تا از این مشکل جلوگیری شود. گرچه این جمله ممکن است قلمبه و سلمبه جلوه کند اما ما هر روزه با مبحث namespace روبرو هستیم.

کامپیوتر یا تلفن همراه خود را در نظر بگیرید (هر سیستم عاملی که داشته باشد)؛ در این سیستم ها، directory هایی که داریم نقش namespace را بازی می کنند. همه می دانیم که فایل foo.txt را می توانیم در دو پوشه جداگانه داشته باشیم.  به طور مثال:

C:\Users\Roxo\Downloads\Documents\foo.txt

C:\Users\Roxo\Downloads\Music\foo.txt

ما یک فایل با یک نام واحد را به طور همزمان در دو مسیر (directory) جداگانه داریم اما می دانیم که این دو فایل به دلیل یکسان بودن نامشان نمی توانند در یک مسیر باشند. اگر بخواهید فایلی را با نام file.txt در مسیری قرار بدهید که فایلی با نام file.txt دارد، فایل دوم فایل اول را جایگزین می کند. این یک پروسه عادی برای همه ماست و همه از آن مطلع هستیم.

در PHP نیز همینطور است و هنگامی که یک تابع با نام function داشته باشیم دیگر نمی توانیم تابعی با همین نام تعریف کنیم. وب سایت رسمی PHP می گوید:

In the PHP world, namespaces are designed to solve two problems that authors of libraries and applications encounter when creating re-usable code elements such as classes or functions:

  1. Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
  2. Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.

ترجمه:

namespaces ها در دنیای PHP برای حل دو مشکل اساسی طراحی شده اند که نویسندگان برنامه ها و کتابخانه ها، هنگام ساخت کدهایی با قابلیت استفاده چند باره، با آن برخورد می کنند:

  1. تصادم نام ها (مشکل یکی بودن نام دو تابع، کلاس و ...) بین کدهایی که خودتان می نویسید و کلاس ها، توابع و ثابت های داخلیِ PHP یا کلاس ها، توابع و ثابت هایی که مربوط به کدهای خارجی (پلاگین، کتابخانه و ...) هستند.
  2. ایجاد قابلیت کوتاه تر کردنِ نام گذاری های بسیار طولانی؛ این نام گذاری ها معمولا برای این استفاده می شوند که از مشکل اول (تصادم نام ها) جلوگیری کنند و یا خوانایی سورس کد را بهبود ببخشند.

قبل از به وجود آمدن namespace ها راه حل خاصی وجود نداشت.

به طور مثال WordPress برای جلوگیری از این مشکل، به نام تمامی فایل ها حروف "_WP" را اضافه می کند. فریم ورک Zend نیز برای دور زدن این مشکل از ساختار خاص و بسیاری طولانی برای نام گذاری فایل هایش استفاده می کند که شبیه "Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive" است.

ما می توانیم ثابت ها، کلاس ها و توابع PHP را در namespace ها قرار دهیم.

نحوه تعریف namespace ها

تمامی ثابت ها، توابع و کلاس های PHP به صورت پیش فرض در فضای global قرار می گیرند. این همان فضایی است که قبل از ساخته شدن namespace ها وجود داشت و نام ها در آن قرار می گرفتند. برای تعریف یک namespace باید از دستور namespace در بالای فایل PHP خود استفاده کنید. توجه کنید که این دستور باید اولین خط در فایل PHP شما باشد (البته به استثناء دستور declare) و اجازه ندارید قبل از آن هیچ whitespace (فضای خالی مانند اسپیس یا اینتر) یا کدهایی به غیر از کد PHP قرار دهید. مثال از کد صحیح:

<?php
// define this code in the MyProject namespace
namespace MyProject;

هر کدی که پس از این کد نوشته شود مربوط به namespace ای به نام MyProject خواهد بود.

مثال از کد غلط:

<html>
<?php
namespace MyProject; // fatal error - namespace must be the first statement in the script
?>

در این کد قبل از کدهای PHP از کدِ HTML استفاده شده است که باعث بروز خطا می شود.

نکته: ما نمی توانیم برای یک گروه از کدها دو یا تعداد بیشتری namespace داشته باشیم. همچنین نمی توانیم به شیوه عادی از namespace ها به صورت "تو در تو" (nested) استفاده کنیم.

کد زیر در PHP غلط است:

<?php
namespace my\stuff {
    namespace nested {
        class foo {}
    }
}
?>

اگر بخواهید از namespace های تو در تو استفاده کنید باید آن را به شکل زیر پیاده کنید:

<?php
namespace my\stuff\nested {
    class foo {}
}
?>

در واقع این یک کد nest شده (تو در تو) نیست، بلکه یک نظام سلسله مراتبی از namespace ها است که در عمل همان کار nest کردن را انجام می دهد.

همچنین می توانید namespace های مختلفی را در یک فایل داشته باشید:

<?php
namespace MyProject1;
// PHP code for the MyProject1 namespace

namespace MyProject2;
// PHP code for the MyProject2 namespace

// Alternative syntax
namespace MyProject3 {
	// PHP code for the MyProject3 namespace
}
?>

اما طبق گفته متخصصین و خود وب سایت PHP این کار اصلا استاندارد نبوده، توصیه نمی شود و تا حد امکان باید از آن دوری کرد. سعی کنید هر namespace را در یک فایل جداگانه داشته باشید.

فراخوانی namespace ها

به نظر من برای نمایش این دستورات بهتر است از یک مثال واقعی استفاده کنیم. ابتدا یک فایل به نام lib1.php می سازیم و در آن یک تابع، یک کلاس و یک ثابت تعریف می کنم. نام namespace آن را نیز App\Lib1 می گذاریم؛ App مخفف Application (به معنی برنامه) و Lib مخفف Library (به معنی کتابخانه) است. محتوای این فایل به شکل زیر است:

<?php
// application library 1
namespace App\Lib1;

const MYCONST = 'App\Lib1\MYCONST';

function MyFunction() {
	return __FUNCTION__;
}

class MyClass {
	static function WhoAmI() {
		return __METHOD__;
	}
}
?>

می توانیم برای فراخوانی یا صدا زدن این کد به شکل زیر عمل کنیم:

فایلی به نام myapp.php می سازیم که محتوای زیر را داشته باشد:

<?php
header('Content-type: text/plain');
require_once('lib1.php');

echo \App\Lib1\MYCONST . "\n";
echo \App\Lib1\MyFunction() . "\n";
echo \App\Lib1\MyClass::WhoAmI() . "\n";
?>

ما هیچ namespace ای را در فایل myapp.php تعریف نکرده ایم بنابراین کدهای آن در فضای global قرار گرفته اند. از طرفی دیگر، اگر MYCONST یا ()MyFunction یا MyClass را مستقیما صدا بزنید با یک خطا مواجه خواهید شد. چرا؟ به دلیل اینکه آن ها در namespace ای به آدرس App\Lib1 هستند اما کدهای ما در فضای global قرار دارند.

برای حل این مشکل (همانطور که در کد بالا می بینید) می توانیم از آدرس کامل App\Lib1\ استفاده کنیم. اگر فایل myapp.php را اجرا کنیم خروجی آن به این شکل خواهد بود:

App\Lib1\MYCONST
App\Lib1\MyFunction
App\Lib1\MyClass::WhoAmI

سوال: مگر قرار نبود یکی از مزایای استفاده از namespace ها این باشد که دیگر مجبور به استفاده از نام های طولانی و غیره نشویم؟ با این پسوند های پشت سر هم، نام ها باز هم طولانی می شوند. این که شد همان آش و همان کاسه!

پاسخ: باید توجه کنید فایده اصلی namespace ها این بود که نیازی به حفظ کردن نام توابع، کلاس ها و ... نداشته باشیم و دور شدن از نام های طولانی تنها یکی از فایده های namespace ها است. در عین حال حرف شما کاملا صحیح است! برای حل این مشکل در جلسه بعد با دستور use آشنا می شویم و اما قبل از آن باید چند اصطلاح را توضیح بدهم تا جلسه بعد مشکلی نداشته باشیم:

نام ها در namespace ها به این شکل هستند:

  • Unqualified name: این نوع نام ها، نام هایی هستند که جدا کننده namespace را ندارند. جدا کننده namespace همان علامت بک اسلش "\" است. مثال: ()MyFunction یا Foo
  • Qualified name: این نوع نام ها، نام هایی هستند که حداقل یک جداکننده namespace دارند. مثال: ()Lib1\MyFunction یا Foo\Bar
  • Fully qualified name: این نوع نام ها، کامل ترین شکل نام هستند و قبل از هر چیز با یک جداکننده namespace شروع می شوند. مانند: ()App\Lib2\MyFunction\ یا Foo\Bar\ و ... . اگر قبلا با اندروید و ویندوز (مخصوصا در زمینه دیرکتوری ها) آشنا باشید می دانید که بک اسلش اولیه که قبل از همه چیز می آید به معنی root (در لغت به معنی "ریشه") یا مبدا دستگاه است. این بک اسلش در namespace ها به معنی namespace اصلی و ریشه ای، یعنی همان فضای global، اشاره می کند.

نام های Fully qualified برای یک بار صدا زدن چیزی کفاف می کنند اما اگر بخواهیم چیزهای زیادی را صدا بزنیم، استفاده از آن ها بسیار سخت می شود و اینجاست که دستور use وارد می شود.

برای درک بهتر این موضوع، دو فایل جداگانه می سازیم و درونشان کدهای یکسانی قرار می دهیم. تنها فرق این دو فایل این است که namespace متفاوتی دارند.

فایل اول lib1.php

<?php
// application library 1
namespace App\Lib1;

const MYCONST = 'App\Lib1\MYCONST';

function MyFunction() {
	return __FUNCTION__;
}

class MyClass {
	static function WhoAmI() {
		return __METHOD__;
	}
}
?>

فایل دوم lib2.php

<?php
// application library 2
namespace App\Lib2;

const MYCONST = 'App\Lib2\MYCONST';

function MyFunction() {
	return __FUNCTION__;
}

class MyClass {
	static function WhoAmI() {
		return __METHOD__;
	}
}
?>

حال برای دنبال کردن ادامه بحث باید با مفاهیم Unqualified name (مانند ()MyFunction) و Qualified name (مانند ()Lib1\MyFunctionو Fully qualified name مانند (()App\Lib2\MyFunction\آشنا باشید.

حتما متوجه شده اید که این نام ها مبحث جدیدی نیستند و زمانی که برای فراخوانی namespace ها آن ها را صدا می زدیم از همین سیستم استفاده می کردیم اما آشنایی شما با آن ها برای ما مهم است.

حالا که فایل های lib2.php و lib1.php را تعریف کرده ایم می خواهیم کدی بنویسیم که تابع، ثابت و کلاس ما را فراخوانی کند. نام این فایل را myapp1.php می گذاریم:

<?php
namespace App\Lib1;

require_once('lib1.php');
require_once('lib2.php');

header('Content-type: text/plain');
echo MYCONST . "\n";
echo MyFunction() . "\n";
echo MyClass::WhoAmI() . "\n";
?>

خروجی این کد به شکل زیر است:

App\Lib1\MYCONST
App\Lib1\MyFunction
App\Lib1\MyClass::WhoAmI

اگر به کدهای بالا توجه کنید، می بینید که ما هر دو فایل lib1.php و lib2.php را include کرده ایم اما ثابت ما (MYCONST)، تابع ما (MyFunction) و کلاس ما (MyClass) تنها از کدهای فایل lib1.php فراخوانی می شوند. می دانید چرا؟ سعی کنید چند لحظه فکر کنید تا خودتان به جواب برسید...

دلیل این است که کدهای lib1.php و کدهای myapp1.php دارای namespace یکسانی هستند و هر دو در AppLib1 قرار دارند اما AppLib2 دارای namespace کاملا جداگانه ای است.

وارد کردن namespace ها در فایل های دیگر با دستور use

برای اینکه مشکل کدهای قبل را حل کنیم می توانیم از دستور use استفاده کنیم. این بار کدها را در فایلی به نام myapp2.php و به این شکل می نویسیم:

<?php
use App\Lib2;

require_once('lib1.php');
require_once('lib2.php');

header('Content-type: text/plain');
echo Lib2\MYCONST . "\n";
echo Lib2\MyFunction() . "\n";
echo Lib2\MyClass::WhoAmI() . "\n";
?>

خروجی این کد به شکل زیر است:

App\Lib2\MYCONST
App\Lib2\MyFunction
App\Lib2\MyClass::WhoAmI

به کدهای بالا توجه کنید؛ ما AppLib2 را وارد فایل خود کرده ایم اما هنوز هم نمی توانیم مستقیما و بدون هیچ پیشوندی به MYCONST و MyFunction و MyClass اشاره کنیم. چرا؟

به دلیل اینکه کدهایی که نوشتیم (فایل myapp2.php) در فضای global قرار دارند و اگر هیچ پیشوند و نام کاملی به ثابت، تابع و کلاس خود ندهیم، PHP در فضای global به دنبال این موارد خواهد گشت. از کجا می دانیم کد ما در فضای global است؟ اگر به کدها نگاهی بیندازید (فایل myapp2.php) متوجه می شوید که برای این فایل هیچ namespace ای تعریف نکرده ایم، بلکه به آن اجازه داده ایم از namespace ای به نام App\Lib2 استفاده کند.

همانطور که پیش تر گفتیم زمانی که برای فایلی namespace تعریف نکنید، آن فایل در فضای global قرار می گیرد اما پیشوند Lib2 به فایل ما می گوید در فضای global دنبال این تابع، ثابت و کلاس نگرد بلکه فلان namespace را جست و جو کن.

مبحث aliasing در namespace ها

کلمه alias در لغت به معنی «نام مستعار» است یا هر اسمی که واقعی نباشد اما به چیزی واقعی اشاره کند.

به طور مثال تخلص شعرا یک نوع alias محسوب می شود چرا که اسم واقعی شان نیست اما به خودشان اشاره دارد. مثلا خواجه شمس‌الدین محمد تخلص خود را حافظ گذاشته است و ما همه می دانیم منظور از حافظ چه کسی است.

این کلمه در مبحث namespace ها معنی آن چنان متفاوتی ندارد! alias به ما اجازه می دهند نام های مستعار و کوتاه تری انتخاب کنیم تا راحت تر کدنویسی کنیم. مثال خود را در فایل به نام myapp3.php می نویسیم:

<?php
use App\Lib1 as L;
use App\Lib2\MyClass as Obj;

header('Content-type: text/plain');
require_once('lib1.php');
require_once('lib2.php');

echo L\MYCONST . "\n";
echo L\MyFunction() . "\n";
echo L\MyClass::WhoAmI() . "\n";
echo Obj::WhoAmI() . "\n";
?>

خروجی این کد به شکل زیر خواهد بود:

App\Lib1\MYCONST
App\Lib1\MyFunction
App\Lib1\MyClass::WhoAmI
App\Lib2\MyClass::WhoAmI

همانطور که متوجه شده اید این کار را با کلمه کلیدی as (به معنی "به عنوان") انجام می دهیم. در کد بالا اولین دستورِ use می گوید:

از این به بعد دوست داریم به جای AppLib1 بگوییم L و هر نام qualified ای که از حرف L استفاده کند، در زمان کامپایل شدن تبدیل به AppLib1 خواهد شد.

بدین صورت می توانیم به جای استفاده از نام های کامل مانند Lib2\MyFunction از نام های کوتاه تری مانند L\MyFunction استفاده کنیم.

دومین دستور use جالب تر است. این خط از کد می گوید به جای کلاسی که در AppLib2 تعریف کرده ایم (MyClass) می‌خواهیم بگوییم Obj. به همین دلیل می توانید از دستوری مانند ()new Obj استفاده کنید. البته این قابلیت تنها مخصوص کلاس ها است و مثلا برای توابع باید از ورژن PHP 5.6 به بالا و از روش دیگری استفاده کنید:

use function My\Full\functionName as func;

نکته: اگر بخواهیم چند namespace را وارد یک فایل کنیم، دو راه داریم:

  • مثل ما چند بار از دستور use استفاده کنیم.
  • یک بار از دستور use استفاده کنیم و namespace های مختلف را با ویرگول از هم جدا کنیم.
    مانند ;use My\Full\Classname as Another, My\Full\NSname

قوانین Name resolution

زمانی که کد شما کامپایل می شود بسیاری از نام هایی که ما به صورت قرار دادی تعیین کرده ایم (مثل alias ها) تبدیل به نام های اصلی می شوند، به این فرآیند Name resolution می گوییم.

برای درک کردن این بحث باید با مفاهیم Unqualified name (مانند ()MyFunction) و Qualified name (مانند ()Lib1\MyFunctionو Fully qualified name مانند (()App\Lib2\MyFunction\آشنا باشید.

اگر با این موارد آشنایی ندارید لطفا دوباره به قسمت تعریف namespace ها در PHP در همین مقاله مراجعه کنید.

البته یک نوع نامگذاری دیگر نیز وجود دارد که به آن Relative name می گوییم؛ در این نام گذاری namespace نیز ذکر می شود. مثال: namespace\Foo\Bar

چند مورد از قوانین اصلی name resolution به این شرح هستند:

  • علامت بک اسلش "\" در نام های Fully qualified برداشته می شوند. به طور مثال A\B\ تبدیل به A\B می شود.
  • نام های qualified و Unqualified با توجه به قوانین import (استفاده از دستور use) ترجمه می شوند. به طور مثال اگر namespace ای به آدرس A\B\C را با کلیدواژه as به C تبدیل کرده باشیم، فراخوانی C\D\E به A\B\C\D\E تبدیل می شود؛ یعنی به نام کامل و صحیحش برمیگردد.

سعی می کنم این قوانین را که بیشتر از دو مورد بالا هستند در یک مثال توضیح دهم تا مطلب کاملا مفهوم شود. من تنها قوانین مهم و کاربردی را ذکر می کنم. می توانید دیگر قوانین را در صفحه رسمی مربوطه در سایت PHP ببینید.

تصور کنید در ابتدای فایل ما این کد وجود دارد:

<?php
namespace A;
use B\D, C\E as F;

با توجه به کد بالا صدا زدن توابع به این شکل اجرا می شود:

foo();
\foo();
my\foo();
F();

برای تابع ;()foo

  • ابتدا سعی می کند تابع foo را در namespace ای به نام A پیدا کند (یعنی namespace اصلی فایل).
  • اگر موفق نشود، سعی می کند تابع foo را در global namespace (فضای global) پیدا کند.

برای تابع ;()foo\

سعی می کند این تابع را در فضای گلوبال پیدا کند.

برای تابع ;()my\foo

سعی می کند تابع foo را در namespace به آدرس A\my پیدا کند.

برای تابع ;()F

  • سعی می کند F را در نیم‌اسپیسِ A پیدا کند.
  • اگر موفق نشد، سعی می کند، تابع F را در فضای global پیدا کند.

ثابت __NAMESPACE__

این دستور همیشه نام namespace فعلی را به صورت یک رشته برمیگرداند:

<?php
namespace App\Lib1;
echo __NAMESPACE__; // outputs: App\Lib1
?>

همانطور که در خود کد توضیح دادیم عبارت "App\Lib1" را به ما برمیگرداند.

نکته: اگر کدهای ما در فضای global باشند، یک رشته خالی به ما برگردانده می شود.

جدا از مزایایی که این دستور در هنگام دیباگ کردن سیستم به ما می دهد، می توان از آن برای تولید نام برای کلاس ها به صورت fully qualified و پویا استفاده کرد:

<?php
namespace App\Lib1;

class MyClass {
	public function WhoAmI() {
		return __METHOD__;
	}
}

$c = __NAMESPACE__ . '\\MyClass';
$m = new $c;
echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
?>

کلیدواژه namespace

در اینجا منظور ما مفهوم namespace (به معنی فضای نام) نیست بلکه منظورمان یک دستور برنامه نویسی به نام namespace است! این دو را اشتباه نگیرید!

می توانیم از دستور namespace برای اشاره مستقیم به یک namespace یا namespace های زیرین (nested شده ها و ...) استفاده کنیم، بنابراین این دستور معادل همان دستور self در کلاس ها است.

اگر از دستور self در کلاس ها چیزی به خاطر ندارید به مقاله زیر مراجعه کنید:

مثال:

<?php
namespace App\Lib1;

class MyClass {
	public function WhoAmI() {
		return __METHOD__;
	}
}

$m = new namespace\MyClass;
echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
?>

نکته: در خط دوم از کد بالا با کلمه namespace مواجه می شویم. این کلمه در اینجا برای تعریف کردن namespace ها است (همان چیزی که قبلا خوانده ایم). اما در خط های پایانی با دستور "new namespace\MyClass" مواجه می شویم. این همان دستوری است که به namespace فعلی اشاره دارد؛ اگر دقت کنید خروجی این کد نیز App\Lib1 را به ما برگردانده است.

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$ می تواند App\Lib1\MyClass باشد. شما می توانید تمام فایل های کلاس هایتان را در یک فولدر قرار دهید و namespace را از رشته برگردانده شده حذف کنید اما این کار توصیه نمی شود چرا که ممکن است باعث تصادم نام فایل ها شود (فایل هایی با نام یکسان و در یک محل).

از طرفی نظام سلسه مراتبی در فایل های کلاس های شما، می توانند دارای ساختاری مشابه با ساختار namespace ها باشند؛ به طور مثال میتوانید فایل MyClass.php را در آدرس classes/App/Lib1/ قرار دهید. به مثال زیر توجه کنید:

محتویات classes\App\Lib1\MyClass.php\ به این شکل است:

<?php
namespace App\Lib1;

class MyClass {
	public function WhoAmI() {
		return __METHOD__;
	}
}
?>

حال، فایلی که در مسیر root (مسیر اصلی و ریشه ای) قرار دارد می تواند از کد زیر استفاده کند:

محتویات فایل myapp.php

<?php
use App\Lib1\MyClass as MC;

$obj = new MC();
echo $obj->WhoAmI();

// autoload function
function __autoload($class) {

	// به آدرس کامل فایل namespace تبدیل
	$class = 'classes\' . str_replace('\\', '/', $class) . '.php';
	require_once($class);

}
?>

نکات این کد:

  • کلاس App\Lib1\MyClass به صورت MC خلاصه نویسی شده (مبحث aliasing)
  • دستور ()new MC در هنگام کامپایل شدن کد، تبدیل به ()new App\Lib1\MyClass می شود.
  • دستور str_replace از این جهت استفاده شده است که تمام بک اسلش "\" های namespace را به فوروارد اسلش "/" تبدیل کند. چرا؟ زیرا مسیر فایل ها همیشه با فوروارد اِسلَش کار می کند. بنابراین App\Lib1\MyClass تبدیل به classes/App/Lib1/MyClass.php شده و همین فایل نیز بارگذاری می شود.

منبع: وب سایت های sitepoint و php

نویسنده شوید

دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

sajjadVa22
29 بهمن 1397
اقا دمت گرم خیلی منتظر این بودم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
29 بهمن 1397
سلام دوست عزیز، ممنونم، لطف دارید.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.