منوها و آیتم‌های منو

مقدمه

کلاس‌های Menu و Menuitem در جوملا، مسئول مدیریت پیکربندی و نمایش منوها و آیتم‌های منو در بخش فرانت‌اند (نمایش سایت به کاربران) هستند. منو مجموعه‌ای از لینک‌های ناوبری است که می‌تواند به صورت منوی اصلی (مثلاً در بالای سایت) یا منوی فرعی (مثلاً در بخش پاورقی) نمایش داده شود. هر لینک ناوبری جداگانه یک آیتم منو (Menuitem) است.

در ساختار کلی یک منو، می‌توانید "زیرمنو" داشته باشید. این زیرمنو به صورت یک ساختار جداگانه Menu در جوملا پیاده‌سازی نشده، بلکه به صورت مجموعه‌ای از آیتم‌های منو زیر یک آیتم منوی والد است. بنابراین، آیتم‌های منو در جوملا به صورت درختی مرتب شده‌اند و از مدل Nested Set برای این ساختار استفاده می‌شود.

این راهنما توضیح می‌دهد که چگونه می‌توانید با استفاده از API جوملا به داده‌های منو و آیتم‌های منو دسترسی پیدا کنید و همچنین نمونه کد ماژولی که قابلیت‌ها را نشان می‌دهد، ارائه می‌کند.

نکته مهم: این کلاس‌ها در بخش مدیریت (backend) جوملا استفاده نمی‌شوند.

عملیات پایه

برای گرفتن اطلاعات تمام آیتم‌های منو در سایت، از کد زیر استفاده می‌کنید:

 
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$sitemenu = $app->getMenu();
 

اگر کد شما در بخش مدیریت جوملا اجرا می‌شود، باید به این شکل عمل کنید:

 
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$sitemenu = $app->getMenu('site');
$sitemenu->load();
 

ساختار `$sitemenu` سپس شامل آیتم‌های تمام منوهای سایت خواهد بود.

(دلیل اینکه در فرانت‌اند نیازی به فراخوانی `load()` نیست، این است که آیتم‌های منو معمولاً قبل از اجرای کد شما بارگذاری شده‌اند، زیرا برای عملکرد روتینگ سایت نیاز هستند. اگر شما پلاگین سیستم سایت می‌نویسید که قبل از روتینگ فراخوانی می‌شود، باید خودتان `load()` را اضافه کنید.)

نکته مهم درباره منوها

API جداگانه‌ای برای گرفتن فقط منوهای سیستم (برخلاف آیتم‌های منو) وجود ندارد. اگر واقعاً به این اطلاعات نیاز دارید، باید به صورت مستقیم از جدول `menu_types` در دیتابیس با کوئری SQL بخوانید. اما می‌توانید از روی ساختار آیتم‌های منو، منویی که هر آیتم متعلق به آن است را پیدا کرده و همه آیتم‌های یک منو را بازیابی کنید.

دسترسی به آیتم‌های منوی خاص

برای دسترسی به آیتم‌های منوی مشخص، از متد `getItems()` با یک فیلتر برای `$sitemenu` استفاده می‌کنیم. برای گرفتن آرایه‌ای از تمام آیتم‌های منو اینگونه عمل کنید:

 
$menuitems = $sitemenu->getItems(array(), array());
 

برای گرفتن آرایه‌ای از تمام آیتم‌هایی که در منوی "mainmenu" هستند، از این استفاده کنید:

 
$mainmenuItems = $sitemenu->getItems('menutype', 'mainmenu');
 

این کد همه آیتم‌های منوی "mainmenu" را، شامل آیتم‌های زیرمنو نیز برمی‌گرداند. اگر می‌خواهید فقط آیتم‌های موجود در بالاترین سطح یا اولین سطح زیرمنوی "mainmenu" را بگیرید، استفاده کنید از:

 
$mainmenuItems = $sitemenu->getItems( array('menutype','level'), array('mainmenu', array("1","2")) );
 

خلاصه اینکه برای فیلتر کردن آیتم‌های منوی خاص، باید آرایه‌ای از ویژگی‌ها (properties) و یک آرایه مربوط از مقادیر لازم به آنها را ارسال کنید.

نکات اضافی

- آیتم‌های منویی که منتشر نشده‌اند برگردانده نمی‌شوند و در ساختار `$sitemenu` نیستند.

- همانطور که قبلاً گفته شد، در بخش مدیریت جوملا چنین متدی وجود ندارد زیرا کلاس‌های Menu و Menuitem استفاده نمی‌شوند؛ برای دریافت اطلاعات منو در بخش مدیریت باید مستقیماً از دیتابیس بخوانید و آنها را تفسیر کنید.

ویژگی‌ها و پارامترها

مشخصات عمومی کلاس Menuitem به شرح زیر است. بیشتر این موارد در تب اول ("جزئیات") فرم «ویرایش آیتم منو» در بخش مدیریت (بک‌اند) هنگام ویرایش یک آیتم منو نشان داده می‌شوند. وقتی یک شیء Menuitem داشته باشید، می‌توانید مستقیم به این ویژگی‌ها دسترسی داشته باشید. مانند مثال زیر:

 
$menuitems = $sitemenu->getItems(array(), array()); foreach ($menuitems as $menuitem) { echo "Itemid: {$menuitem->id}"; }

 

ویژگی‌های عمومی کلاس Menuitem:

- id– شناسه آیتم منو است. در کد جوملا معمولاً با نام Itemid شناخته می‌شود تا از شناسه‌های دیگر مثل مقاله که ممکن است در آدرس‌ها ظاهر شوند، متمایز باشد.

- menutype– مشخص‌کننده منویی است که این آیتم به آن تعلق دارد. شناسه‌ای یکتا برای نوع منو است که هنگام ساخت منو تعیین می‌کنید.

- title– عنوانی که هنگام نمایش آیتم منو نشان داده می‌شود (نام منو در فرم).

- alias– بخشی از آدرس URL در حالت استفاده از SEF URLها.

- note– یادداشت اختیاری که در فرم نشان داده می‌شود.

- route– بخشی از URL SEF که به این آیتم منو می‌رسد. مثلا اگر alias این آیتم "me"، والد آن "dad" و جد بزرگ آن در بالاترین سطح منو "gran" باشد، مقدار route برابر "gran/dad/me" خواهد بود.

- link– آدرسی که در فیلد لینک فرم قرار دارد.

- type– معمولاً مقدار آن "component" است که لینک به تابع یک کامپوننت در جوملا اشاره دارد. اما ممکن است یکی از موارد زیر باشد در صورتی که نوع آیتم منو یکی از لینک‌های سیستمی باشد:

    - "heading" – عنوان منو (سرصفحه‌ای برای آیتم‌های زیرمنو)

    - "alias" – نمایه‌ای به آیتم منوی دیگر

    - "separator" – جداکننده (مثلاً خط تیره) برای تفکیک آیتم‌های منو

    - "url" – آدرس خارجی (یک لینک به URL بیرونی)

- level– سطح قرارگیری در ساختار درختی منو. نقطه ریشه (root) سطح صفر است، آیتم‌های اصلی منو سطح ۱ و هر زیرمنو به ترتیب سطوح ۲، ۳ و غیره دارند.

- language– کد زبان مرتبط، مانند "es-ES".

- browserNav– گزینه‌ای که مربوط به فیلد «پنجره هدف» در فرم است. معمولاً شامل این مقادیر است:

    - 0 – همان پنجره (تب) جاری باز می‌شود

    - 1 – پنجره جدید همراه با نوار ناوبری (تب جدید)

    - 2 – پنجره جدید بدون نوار ناوبری باز می‌شود

- access– شناسه سطح دسترسی (AccessLevel) اختصاص یافته به این آیتم منو. API بررسی می‌کند که کاربر فعلی چه منوهایی را مجاز است مشاهده کند و فقط آن‌ها را باز می‌گرداند.

- home– مشخص می‌کند آیا این آیتم منو صفحه اصلی (صفحه پیش‌فرض) سایت یا زبان است یا نه.

- img– دیگر استفاده نمی‌شود. قبلاً می‌شد تصویری تعیین کرد اما اکنون تصویر منو در تب «نوع لینک» فرم مشخص شده و در پارامتر "menu_image" ذخیره می‌شود.

- template_style_id– شناسه استایل قالب وارد شده در فرم.

- component_id– شناسه کامپوننت مربوط به این آیتم منو.

- parent_id– شناسه والد در ساختار درختی آیتم‌های منو.

- component– نام کامپوننت مرتبط، مانند "com_contact".

- tree– آرایه‌ای از شناسه‌های آیتم‌های منو از ریشه تا این آیتم. مثلا اگر آیتم منو id=789، والد id=456 و جد id=123 باشد که جد در بالاترین سطح قرار دارد، این آرایه به صورت '("123", "456", "789")' خواهد بود.

- query– آرایه‌ای انجمنی از پارامترهای پرس‌وجو که در فیلد لینک فرم مشخص شده‌اند. مثلا برای آیتمی که به یک مقاله اشاره دارد، به شکل زیر است: 

 
`array("option" => "com_content", "view" => "article", "id" => "123")`

 

پارامترهای اضافی ذخیره شده در params

بقیه ویژگی‌های آیتم منو در فیلد **params** در دیتابیس ذخیره شده‌اند و از طریق متد `getParams()` خوانده می‌شوند. تعداد این ویژگی‌ها بسیار زیاد و متنوع است و نمی‌توان همه را اینجا نام برد. دو مثال:

 
params = $menuitem->getParams();
$displayed = $params->get("menu_show");
$show_tags = $params->get("show_tags");
 

- متغیر `$displayed` یک مقدار بولی است که تعیین می‌کند آیا آیتم منو باید در منو نمایش داده شود یا خیر، مطابق تنظیم «نمایش در منو» در تب نوع لینک فرم.

- متغیر `$show_tags` یک مقدار بولی است که مشخص می‌کند آیا برچسب‌های مرتبط با محتوای آیتم نمایش داده شوند یا نه. این پارامتر فقط در صورت مرتبط بودن (مثلاً برای مقاله یا مخاطب) فعال است و اگر آیتم به فرم جستجو یا نتایج جستجو مربوط باشد، غیرمرتبط و غیرفعال است.

توضیح بیشتر درباره پارامترها

برخی از این پارامترها (مثلاً آنهایی که در تب نوع لینک فرم ویرایش آیتم منو تعیین می‌شوند) ممکن است برای آیتم‌های منویی به صورت کلی تعریف شده باشند، اما پارامترهای ذخیره شده وابسته به نوع آیتم منو (ویژگی type) متفاوت است.

برای دیدن آنها، می‌توانید فایل‌های XML مربوط به فرم ویرایش آیتم را در مسیر زیر پیدا کنید:

administrator/components/com_menus/forms/item_<type>.xml

که در آن `<type>` باید با نوع مد نظر جایگزین شود (مثل component، alias، separator و غیره).

این فایل‌های XML بخش‌هایی از فرم «ویرایش آیتم منو» را تعریف می‌کنند و نام پارامترهایی که در رشته JSON پارامترها در دیتابیس ذخیره شده و توسط `getParams()->get()` خوانده می‌شوند، مشخص است.

پارامترهای مرتبط با کامپوننت هدف

پارامترهای دیگری نیز وجود دارند که مربوط به کامپوننتی هستند که این آیتم منو به آن می‌رسد و ویژگی‌هایی درباره چگونگی نمایش خروجی آن کامپوننت در صفحه خاص دارند.

برای مشاهده این پارامترها، باید فایل XML مربوط به آن صفحه در پوشه قالب (layout) کامپوننت را بیابید.

مثلاً برای صفحه‌ای که یک مخاطب (contact) را نمایش می‌دهد معمولاً مسیر فایل به صورت زیر است:

components/com_contact/tmpl/contact/

دریافت آیتم‌های منوی جداگانه

علاوه بر روش‌هایی که در بالا برای فیلتر کردن و پیدا کردن آیتم منوی مورد نظر توضیح داده شد، روش‌هایی هم وجود دارد که به طور مستقیم به برخی آیتم‌های منو دسترسی پیدا کنیم.

آیتم منوی فعال

آیتم منوی فعال یک صفحه وب سایت به آیتم منویی گفته می‌شود که جوملا از آن برای تعیین نحوه نمایش آن صفحه استفاده می‌کند (مثلاً با استفاده از سبک قالب تعریف شده برای آن آیتم منو). برای یافتن این آیتم از کد زیر استفاده می‌کنیم:

 
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$sitemenu = $app->getMenu();
$activeMenuitem = $sitemenu->getActive();
 

سپس می‌توانید ویژگی‌ها و پارامترهای این آیتم منو را همان‌طور که در بالا توضیح داده شد، دریافت کنید.

با این حال، توجه داشته باشید که در برخی موارد نادر آیتم منوی فعال تنظیم نشده است (مثل زمانی که آدرس‌های SEF به شکل /component/com_xxx باشند.)

آیتم منوی پیش‌فرض

برای یافتن آیتم منوی پیش‌فرض یک زبان، می‌توانید به عنوان مثال از کد زیر استفاده کنید:

 
$menuitem = $sitemenu->getItem($itemid);

 

(وقتی در پنل مدیریت فهرست آیتم‌های منو را مشاهده می‌کنید، این همان آیتم منویی است که علامت پرچم کشور کنار آن تنظیم شده است)

تنظیم آیتم‌های منو

شما می‌توانید ویژگی‌ها و پارامترهای آیتم منو را به این شکل تنظیم کنید:

 
$menuitem->setParams($params);     // تنظیم مقادیر پارامترها
$sitemenu->setActive($itemid);     // تنظیم آیتم منوی فعال
 

یا به سادگی مقادیر مختلفی به ویژگی‌های عمومی آیتم منو اختصاص دهید. اما این تغییرات در پایگاه داده ذخیره نمی‌شوند و فقط تا پایان پردازش درخواست HTTP فعلی باقی می‌مانند.

در ادامه کد نمونه یک ماژول ساده جوملا را داریم که می‌توانید آن را نصب و اجرا کنید تا نحوه استفاده از API آیتم‌های منو را مشاهده کنید.

مراحل ایجاد ماژول

1. یک پوشه به نام mod_sample_menu بسازید.

2. در این پوشه دو فایل زیر را ایجاد کنید.

فایل `mod_sample_menu.xml`

 
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
    <name>Menu demo</name>
    <version>1.0.1</version>
    <description>Code demonstrating use of Joomla APIs related to Menus and Menu Items</description>
    <files>
        <filename module="mod_sample_menu">mod_sample_menu.php</filename>
    </files>
</extension>
 

فایل `mod_sample_menu.php`

 
<?php
defined('_JEXEC') or die('Restricted Access');
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$input = $app->input;
$sitemenu = $app->getMenu();
if ($activeMenuitem = $sitemenu->getActive())
{
    echo "Active menuitem is Itemid: {$activeMenuitem->id}<br>";
}
else
{
    echo "No active menuitem<br>";
}
if ($input->exists('menulanguage'))
{
    $lang = $input->get('menulanguage', "", "STRING");
}
else
{
    $lang = $app->getLanguage()->getTag();
}
echo "Getting details for language {$lang}<br>";
$menuitems = $sitemenu->getItems(array("language"), array($lang));
echo "<br>---- properties of menuitems ----<br>";
foreach ($menuitems as $menuitem)
{
    echo "<br>Itemid: {$menuitem->id}, title: {$menuitem->title}, type: {$menuitem->type}<br>";
    echo "<br>Language: {$menuitem->language}, level: {$menuitem->level}<br>";
    $params = $menuitem->getParams();
    if (!($displayed = $params->get("menu_show")))
    {
        echo "This menu item is hidden<br>";
    }
    if ($img = $params->get("menu_image"))
    {
        $imgURL = JURI::root() . $img;
        echo "Image: {$img}<br><img src='{$imgURL}'><br>";
    }
}

 

نحوه نصب و اجرای ماژول:

1. پوشه mod_sample_menu را فشرده (zip) کرده و فایل زیپ آن را به نام mod_sample_menu.zip بسازید.

2. وارد پنل مدیریت جوملا شوید.

3. به بخش “نصب افزونه‌ها” (Install Extensions) بروید.

4. در تب “بارگذاری بسته فایل” (Upload Package File) فایل zip ساخته‌شده را آپلود کنید تا ماژول نصب شود.

5. برای اینکه ماژول نمایش داده شود:

   - به صفحه ماژول‌ها رفته و این ماژول را بیابید.

   - وضعیتش را روی “منتشر شده” (Published) بگذارید.

   - موقعیت نمایش ماژول را انتخاب کنید.

   - در تب اختصاص منو (menu assignment) مشخص کنید در کدام صفحات نمایش داده شود.

نتیجه نهایی در سایت:

- شناسه (Itemid) آیتم منوی فعال در صفحه نمایش داده می‌شود.

- مجموعه‌ای از ویژگی‌های آیتم‌های منویی که زبان آن‌ها مطابق با زبان جاری یا پارامتر URL تعیین‌شده است نشان داده می‌شود.

- برخی ویژگی‌های پارامترها (مثل وضعیت نمایش آیتم منو و هر تصویری که به آیتم الصاق شده باشد) نیز نمایش داده می‌شوند.

نکته:

برای نمایش اطلاعات آیتم‌های منو به زبان‌های دیگر، می‌توانید در URL صفحه، پارامتری مثل `?menulanguage=fr-FR` اضافه کنید.