فضاهای نام (namespaces)

Namespacing به تدریج برای کلاس های جوملا بیش از تعدادی از نسخه های جوملا 3.x معرفی شد. در جوملا 4 تقریباً تمام کلاس های جوملا دارای فضای نام بودند و انتظار می رفت که افزونه های جوملا نیز دارای فضای نام باشند.

اگر با فضای نام پی اچ پی آشنایی ندارید، می توانید اطلاعات کلی را به صورت آنلاین پیدا کنید، به عنوان مثال در https://www.php.net/manual/en/language.namespaces.php

این مستندات جوملا بر نحوه پیاده سازی فضای نام در جوملا تمرکز دارد. ممکن است این ویدیو در مورد فضای نام نیز برای شما مفید باشد.

یافتن فایل های کلاس با PSR4

فضاهای نام به ما اجازه می دهند کلاس های PHP خود را به روشی مشابه که دایرکتوری ها به ما اجازه می دهند، فایل های خود را سازماندهی کنیم. به طور خاص، توصیه PSR4 که جوملا از آن استفاده می‌کند، ما را قادر می‌سازد تا مشخص کنیم یک کلاس خاص باید در چه فایلی باشد.

برای مشاهده این، اجازه دهید مثالی از یک فایل در آدرس زیر را به شما ارائه دهیم:

administrator/components/com_content/src/View/Articles/HtmlView.php

این مسیر حاوی کد نمایه ای است که مقالات را به مدیر ارائه می دهد. این فایل حاوی خطوط زیر است:

namespace Joomla\Component\Content\Administrator\View\Articles;

...

class HtmlView extends BaseHtmlView { …

بنابراین نام کاملاً واجد شرایط (FQN) کلاس زیر است:

\Joomla\Component\Content\Administrator\View\Articles\HtmlView

جوملا فهرستی از رشته‌های پیشوند فضای نام را نگه می‌دارد و رشته‌ای را که شامل نام کلاس کاملاً واجد شرایط است با آن لیست، مقایسه می‌کند که از سمت چپ نام کلاس شروع می‌شود تا ببیند آیا می‌تواند تطابق جزئی پیدا کند. در این مثال، پیشوند فضای نام زیر مطابقت دارد "Joomla\Component\Content\Administrator"

این پیشوند فضای نام دارای یک فهرست مرتبط در داخل سیستم فایل است که نقطه شروع برای یافتن کلاس ها است. در این مورد دایرکتوری administrator/components/com_content/src است. (ما به زودی خواهیم دید که چگونه پیشوندهای فضای نام و دایرکتوری های مرتبط تعریف می شوند).

سپس پیشوند فضای نام منطبق را از FQN حذف می‌کند و \View\Articles\HtmlView را ترک می‌کند و این را به عنوان مسیر پایین از فهرست بالا در نظر می‌گیرد. بنابراین مسیر کامل فایل این است:

administrator/components/com_content/src/View/Articles/HtmlView.php

نمودار تصویری از این موضوع را نشان می دهد.

نمودار تصویری فضاهای نام

پیشوندهای فضای نام جوملا

جوملا پیشوندهای فضای نام و نگاشت آنها را به موقعیت در سیستم فایل برای موارد زیر نگه می دارد:

کامپوننت ها

'Joomla\Component\<Component name>\Administrator\'

اشاره می کند به:

administrator/components/com_<component name>/src

'Joomla\Component\<Component name>\Site\'

اشاره می کند به:

components/com_<component name>/src

'Joomla\Component\<Component name>\Api\'

اشاره می کند به:

api/components/com_<component name>/src

به عنوان مثال:

'Joomla\Component\Content\Administrator'

اشاره می کند به:

administrator/components/com_content/src

ماژول ها

'Joomla\Module\<Module name>\Administrator\'

اشاره می کند به:

administrator/modules/mod_<module name>/src

 

'Joomla\Module\<Module name>\Site\'

اشاره می کند به :

modules/mod_<module name>/src

به عنوان مثال:

'Joomla\Module\Login\Site'

اشاره می کند به:

modules/mod_login/src

پلاگین ها

'Joomla\Plugin\<Plugin type>\<Plugin name>\'

اشاره می کند به

plugins/<plugin type>/<plugin name>/src

به عنوان مثال:

'Joomla\Plugin\Fields\Calendar'

اشاره می کند به:

plugins/fields/calendar/src

کلاس های کتابخانه (Library Classes)

"Joomla\CMS" به libraries/src اشاره می کند. توجه داشته باشید که اینها کلاس هایی هستند که در اسناد API در سمت CMS جوملا توضیح داده شده اند.

'Joomla\SomethingElse'

اشاره می کند به:

libraries/vendor/somethingelse/src

به عنوان مثال:

'Joomla\Event'

اشاره می کند به:

libraries/vendor/event/src

توجه داشته باشید که اینها کلاس هایی هستند که در اسناد API در سمت Framework توضیح داده شده اند.

(به عنوان یک نکته، فقط توجه داشته باشید که اگر یک کلاس در سمت CMS از یک کلاس در سمت Framework ارث ببرد، ممکن است همه متدهای موجود در اسناد API نباشند. به عنوان مثال، کلاس Joomla\CMS\Application\WebApplication دارای متدهایی مانند setHeader است زیرا Joomla\Application\AbtractWebAplication را گسترش می دهد اما این تابع در WebApplication doc لیست نشده است.)

اگر نام کلاسی کتابخانه با «Joomla» شروع نشود، در یکی از دایرکتوری‌های دیگر زیر libraries/vendor/ یافت می‌شود.

(توجه داشته باشید که تمام موارد بالا استاندارد کلی برای کد جوملا است - اما ممکن است استثنای عجیبی پیدا کنید).

اگر به administrator/cache/autoload_psr4.php نگاه کنید، تمام پیشوندهای فضای نام کامپوننت ها، ماژول‌ها و افزونه‌های جوملا را به همراه موقعیت مرتبط در سیستم فایل (و همچنین پیشوندهای فضای نام هر برنامه افزودنی نصب شده) مشاهده خواهید کرد.

نام کلاس های تکراری

قبل از معرفی فضای نام جوملا نام کلاس های تکراری زیادی داشت، به عنوان مثال. برای com_example، کد مدل MVC در کلاس ExampleModelExample هم برای سایت و هم برای مدیر، با هر دو کلاس در فضای نام سراسری است. این مانعی برای اشتراک‌گذاری کد ایجاد می‌کند - به عنوان مثال، نمی‌توانید کلاس مدل سایت شما را از کلاس مدل مدیریت خود به ارث ببرد.

با فضای نام جوملا، FQN های سایت و مدل مدیر متفاوت است، زیرا در فضای نام متفاوت هستند. این کار اشتراک کد بین آنها را بسیار آسان می کند - فقط باید اجازه دهید یک کلاس مدل از دیگری ارث ببرد.

<?php

namespace Mycompany\Component\Example\Site\Model;



use Mycompany\Component\Example\Administrator\ExampleModel as AdministratorModel;



class ExampleModel extends AdministratorModel {

یک هشدار: اگرچه جوملا FQN های منحصر به فردی برای همه کلاس ها دارد، برخی از کلاس های کتابخانه جوملا وجود دارند که آخرین بخش FQN را به اشتراک می گذارند، به عنوان مثال:

رجیستری ممکن است به Joomla\Registry\Registry (یک کلاس کاربردی برای نگهداری ساختارهای داده) یا Joomla\CMS\HTML\Registry (کلاسی برای نگهداری قطعات HTML مورد استفاده در فراخوانی های HtmlHelper::_()) اشاره داشته باشد.

CategoryFactory ممکن است به فضای نام زیر اشاره کند

 Joomla\CMS\Extension\Service\Provider\CategoryFactory

یا به Joomla\CMS\Categories\CategoryFactory اشاره داشته باشد - چندین نمونه مشابه وجود دارد که در آن آخرین بخش از FQN ممکن است به کلاس Factory یا کلاس ارائه دهنده سرویس که در Factory dependency را ثبت می کند اشاره داشته باشد.

DispatcherInterface ممکن است به Joomla\CMS\Dispatcher\DispatcherInterface (Interface Dispatcher برای کامپوننت ها و ماژول ها) یا Joomla\Event\DispatcherInterface (Interface Dispatcher برای پلاگین ها) اشاره داشته باشد.

فقط باید مراقب باشید که عبارت "use" را بررسی کنید تا ببینید دقیقاً به کدام کلاس اشاره شده است.

تعریف پیشوند فضای نام شما

کامپوننت ها

هنگامی که یک پسوند جوملا را توسعه می دهید، فضای نامی را که می خواهید در فایل مانیفست خود استفاده کنید، تعریف می کنید، به عنوان مثال برای com_example:

<namespace path="src">Mycompany\Component\Example</namespace>

بیایید به قسمت های مختلف این نگاه کنیم:

  • Mycompany - شما آزادید هر چیزی را که دوست دارید در اینجا قرار دهید - معمولاً نام شرکتی که برنامه افزودنی را توسعه داده است نشان می دهد.
  • Component – اگر افزونه جوملا شما کامپوننت است، باید روی Component تنظیم شود
  • Example - این باید با نام کامپوننتی که در حال توسعه آن هستید مطابقت داشته باشد
  • src – این زیرپوشه ای است که فایل های کلاس خود را در آن ذخیره می کنید. لازم نیست آن را اینگونه بنامید، اما این یک عمل رایج است.

از این فایل مانیفست جوملا 2 پیشوند فضای نام ایجاد می کند:

'Mycompany\Component\Example\Site'

اشاره می کند به:

components/com_example/src

 

'Mycompany\Component\Example\Administrator'

اشاره می کند به:

administrator/components/com_example/src

(با فرض اینکه شما هر دو جنبه سایت و مدیر برای کامپوننت خود دارید).

ماژول ها

برای ماژول ها هم همین کار را انجام می دهید:

<namespace path="src">Mycompany\Module\Example</namespace>

<files>

<filename module="mod_example">mod_example.php</filename>

<folder>src</folder>

<folder>tmpl</folder>

</files>

تطبیق "Example" در فضای نام با "mod_example" - نام ماژول - ضروری نیست، اما احتمالاً انجام این کار برای شما آسان تر خواهد بود.

اگر این یک ماژول سایت است، جوملا پیشوند فضای نام را ایجاد می کند:

'Mycompany\Module\Example\Site'

اشاره می کند به:

modules/mod_example/src

اگر این یک ماژول مدیریت است، جوملا پیشوند فضای نام را ایجاد می کند:

'Mycompany\Module\Example\Administrator'

اشاره می کند به:

administrator/modules/mod_example/src

پلاگین ها

برای پلاگین ها:

<namespace path="src">Mycompany\Plugin\Content\Example</namespace>

<files>

    <filename plugin="example">example.php</filename>

    <folder>src</folder>

</files>

در اینجا یک بخش اضافی در فضای نام وجود دارد که باید روی نوع پلاگین تنظیم شود - «Content » در مثال بالا.

یک بار دیگر یادآوری میشود که لازم نیست بخش 'Example' در فضای نام دقیقاً با نام plugin="example" مطابقت داشته باشد.

برای موارد فوق جوملا پیشوند فضای نام را ایجاد می کند:

'Mycompany\Plugin\Content\Example'

اشاره می کند به:

plugins/content/example/src

حروف بزرگ

مراقب باشید که حروف بزرگ در قسمت‌هایی از نام کلاس کاملاً واجد شرایط مطابق با حروف بزرگ در نام فهرست‌ها و فایل‌ها باشد! اگر در ویندوز توسعه می دهید افزودنه شما کار خواهد کرد اما اگر سیستم مورد نظر شما لینوکس است، ممکن است متوجه شوید که روی سیستم هدف شما کار نمی کند. این به این دلیل است که اگر در نام فایل‌ها یا نام دایرکتوری‌های خود حروف بزرگ اشتباهی داشته باشید، ویندوز نادیده می گیرد – همچنان فایل را برای شما باز می‌کند – اما لینوکس اینطور نیست و به حروف بزرگ و کوچک حساس است.

پیدا کردن کلاس های خود

هنگامی که در مورد فضاهای نام خود تصمیم گرفتید، می توانید محل قرارگیری فایل های کلاس خود را مرتب کنید. کامپوننت های جوملا از یک ساختار دایرکتوری نسبتاً مسطح تحت src استفاده می کنند، اما شما به آن پایبند نیستید. تا زمانی که به توصیه PSR4 برای تطبیق نام کلاس های کاملا واجد شرایط با مسیرهای فایل پایبند باشید، جوملا فایل های منبع کلاس های شما را پیدا می کند. روزهایی که مجبور بودید حدس بزنید فایل کمکی خود را در چه دایرکتوری ذخیره کنید و چه نامی برای دادن فایل انتخاب کنید، گذشته است!

با این حال، یک مورد وجود دارد که در آن شما باید به جوملا کمک کنید - به شکل فایل های XML.

  • اگر یک فیلد سفارشی تعریف می کنید، باید به جوملا بگویید کلاسی را که آن فیلد سفارشی را تعریف می کند، کجا پیدا کند.
  • اگر یک قانون اعتبار سنجی سفارشی تعریف می کنید، باید به جوملا بگویید کلاسی را که آن قانون را تعریف می کند، کجا پیدا کند.

از آنجایی که فایل‌های XML مانند زبان PHP عبارت <namespace> ندارند، باید معادل آن را ارائه دهید، و ساده‌ترین کار را با گنجاندن یک ویژگی addfieldprefix یا addruleprefix در یک عنصر XML که محل استفاده از آنها را محصور می‌کند، انجام دهید، به عنوان مثال:

<?xml version="1.0" encoding="utf-8"?>

<form

    addruleprefix="Mycompany\Component\Example\Administrator\Rule"

    addfieldprefix="Mycompany\Component\Example\Administrator\Field"

>

فضای نام سراسری PHP

اگر یک عبارت <namespace> در فایل منبع PHP خود داشته باشید، PHP فرض می‌کند که هر نام کلاسی که در کد خود به آن اشاره می‌کنید، در آن فضای نام قرار خواهد گرفت. بنابراین اگر از کلاس‌های استاندارد PHP مانند Exception استفاده می‌کنید، باید قبل از آنها یک علامت بک اسلش \Exception قرار دهید. بک اسلش در ابتدا به PHP نشان می دهد که این یک نام کلاس کاملاً واجد شرایط است و از آنجایی که فقط یک بخش در این FQN وجود دارد در فضای نام جهانی یافت می شود.

به طور مشابه، اگر از یک تابع استفاده می کنید، PHP سعی می کند آن تابع را در فضای نام شما پیدا کند. اما برخلاف کلاس‌ها، اگر تابعی را در فضای نام شما پیدا نکند، به جستجوی آن در فضای نام سراسری باز می‌گردد. بنابراین اگر به PHP بگویید با قرار دادن پیشوند نام تابع با اسلش معکوس، به عنوان مثال \strlen(...) به PHP بگویید که به خود زحمت نگاه کردن به فضای نام خود(سراسری) را نداشته باشد. شما گاهی اوقات این را در کدهای پی اچ پی جوملا خواهید دید.

کلاس Autoloading

یک نمونه جوملا حاوی هزاران فایل منبع PHP با تعداد قابل ملاحظه ای از کلاس های PHP است. بدیهی است که انجام یک نیاز از هر فایل منبع، برای آگاه کردن مفسر PHP از همه کلاس ها، غیر عملی است. پس چگونه جوملا می تواند از دریافت خطای PHP Class Not found در کلاسی که مفسر PHP آن را تشخیص نمی دهد، جلوگیری کند؟ پاسخ این است که از class autoloading (بارگذاری خودکار کلاس) استفاده می کند.

هنگامی که جوملا مقدار دهی اولیه می کند، تعدادی autoloaders را با استفاده از تابع setup() واقع در (libraries/loader.php) تنظیم می کند. ، به عنوان مثال:

spl_autoload_register(['JLoader', 'loadByPsr']);

اگر مفسر PHP با خطی مانند:

if (class_exists($classname)) ...

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

 

loadByPsr($classname)

نام کلاس از جوملا 4 به بعد تغییر کرده است بطوری که باید یک نام کلاس کاملاً واجد شرایط باشد.

مسئولیت autoloader این است که سعی کند فایل منبع حاوی آن کلاس را پیدا کند و یک include_once روی آن انجام دهد تا PHP از آن کلاس آگاه شود. برای کامپوننت‌ها، ماژول‌ها و افزونه‌ها (هم جوملا و هم پسوندهای شخص ثالث) جوملا از روش PSR4 برای نگاشت نام کلاس‌ها برای فایل‌های منبع استفاده می‌کند.

جوملا در طول راه‌اندازی اولیه، از طریق کامپوننت ها، ماژول‌ها و دایرکتوری‌های پلاگین ‌ها هم برای سایت و هم برای مدیر نگاه می‌کند تا همه فایل‌های مانیفست XML را پیدا کند. سپس XML را بارگذاری می‌کند و به دنبال عناصر <namespace> می‌گردد و از آن عناصر مجموعه‌ای از نگاشت پیشوندهای فضای نام را به فهرست‌ها می‌سازد. از آنجایی که این کار مستلزم کمی کار است، نتیجه در administrator/cache/autoload_psr4.php ذخیره می شود – به این مسیر بروید و نگاهی به آن بیندازید!

سپس تابع loadByPsr از این نقشه برداری و قوانین PSR4 برای یافتن فایل های منبع شرح داده شده در Finding classes with PSR4 استفاده می کند تا نام فایلی را که باید حاوی آن کلاس باشد، تعیین کند. بررسی می‌کند که آیا فایل وجود دارد یا نه و اگر وجود دارد، include_once را روی آن اجرا می‌کند و برمی‌گرداند.

اگر تابع loadByPsr کلاس را با موفقیت پیدا کرده باشد، آنگاه PHP عبارت class_exists($classname) را به عنوان فعلی درست در نظر می گیرد و کد را ادامه می دهد. اگر ناموفق بود، PHP استثنای  the class not found را اجرا می کند.

جوملا تعدادی تابع autoloader دارد - همه کلاس ها با استفاده از PSR4 بارگذاری نمی شوند.

برای مثال، کلاس‌های کتابخانه‌ها همگی نگاشت FQN به فایل منبع فردی آن کلاس دارند. می توانید برای بررسی بیشتر به کتابخانه‌ها مسیر /vendor/composer/autoload_classmap.php نگاهی بیندازید.

همچنین یک نقشه برداری در مسیر (libraries/classmap.php) وجود دارد تا از نام های قدیمی کتابخانه های سراسری که با J (به عنوان مثال JModelAdmin) شروع می شود را بررسی میکند تا معادل FQN آن را تعیین کند ، اما این در جوملا 6 ناپدید خواهد شد.