菜单和菜单项
引言
Joomla 菜单和菜单项类管理网站前面对菜单和菜单项的配置和显示。菜单是一组导航链接,你可以将其用作主菜单(如位于网站顶部)或辅助菜单(如位于页脚)。每个单独的导航链接都是一个菜单项。
在整体菜单结构中,你可以使用“子菜单”。这不是 Joomla 菜单构造的方式,而是一组位于父菜单项下方的菜单项。因此,Joomla 菜单项是在有序树结构中实现的,具体使用Nested Set 模型。
本文档介绍如何使用 Joomla API 访问菜单和菜单项数据,并且包括可作为功能演示安装到网站上的示例模块代码。
请注意,这些类不用于管理员后端。
基本操作
若要获取站点上所有菜单项的详细信息,请执行以下操作
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$sitemenu = $app->getMenu();
如果代码在 Joomla 后端运行,则应执行以下操作
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$sitemenu = $app->getMenu('site');
$sitemenu->load();
然后,$sitemenu
结构将包含有关所有站点菜单项的条目。
(不需要在前段调用 load
的原因是,在运行代码时很可能会已加载菜单项,因为它们是站点路由器功能必需的。如果您编写的站点系统插件在路由器之前被调用,那么需要自己添加 load
调用。)
Joomla API 无法使您仅获取系统上的菜单集(而不是菜单项集),因此如果您确实需要这些菜单,那么唯一的办法是直接使用 SQL 查询从 menu_types
表读取数据。但您可以从(如下所述的菜单项结构)中找到该菜单项所属的菜单,以及找到特定菜单的所有菜单项。
为了处理各个菜单项,我们使用 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")));
总之,若要筛选所需的特定菜单项,请传递一个属性数组(来自下一部分中的列表)和这些属性应具有的一个对应值数组。
不会返回未发布的菜单项。它们不包含在 $sitemenu
结构中。
如上所述,没有等效的方法可以在管理员后端获取菜单项,因为没有使用菜单和菜单项类。如果您想访问菜单详细信息,则必须从数据库中读取和解释相应记录。
属性和参数
以下为 Menuitem 类的公有属性。其中大多数在后台编辑菜单项时,"菜单:编辑项"表单的第一个标签页("详细信息")中显示。获取 Menuitem 对象后,您可以直接访问属性,如下所示。
$menuitems = $sitemenu->getItems(array(), array());
foreach ($menuitems as $menuitem)
{
echo "Itemid: {$menuitem->id}";
}
- id – 这是菜单项的 ID。在 Joomla 代码中,通常称为 Itemid,可能是为了与例如文章的 ID 区分(因为这两个 ID 通常在不使用 SEF URL 的情况下显示在 URL 中)。
- menutype – 这标识了菜单项所属的菜单。这是一个您分配给菜单的唯一标识符菜单类型。
- title – 当菜单项在菜单上显示时显示的内容(在表单中称为"菜单标题")。
- alias – 使用 SEF URL 时的 URL 片段。
- note – 表单上显示的可选备注。
- route – 此菜单项的 SEF URL 部分。例如,如果此菜单项的别名为"me",其父级的别名为"dad",其祖级的别名(在菜单的顶层)为"gran",则返回的路由为"gran/dad/me"。
- link – 在表单的链接字段中显示的链接。
- type – 通常情况下,这将是"component"且链接会指向 Joomla 中的组件功能。但是,当选择的菜单项类型是系统链接之一时,它也可能是以下之一:
- "heading" – 菜单标题 – 子菜单项父级的标题。
- "alias" – 菜单项别名 – 到另一个菜单项的别名。
- "separator" – 分隔符 – 分隔菜单中项的文本字符串(例如连字符)。
- "url" – URL – 到外部 URL 的链接。
- level – 菜单项树中的级别。树底部的"根"条目级别为"0",菜单中顶层的菜单项级别为"1",第一级子菜单级别为"2",以此类推。
- language – 语言代码。例如,"es-ES"。
- browserNav – 与表单的目标窗口字段中输入的选项关联的值。通常这意味着以下内容;
- 0 – 父级 – 链接在同一个标签页打开。
- 1 – 带导航的新窗口 – 链接在新标签页打开。
- 2 – 不带导航的新窗口 – 链接在新窗口打开。
- access – 分配给此菜单项的访问级别的 ID。使用此 API 时,会检查登录用户,并且仅会返回该用户允许查看的那些菜单项。
- home – 该项是否为网站或语言的主页("默认页面")。
- img – 现在似乎不再使用此项。您可以指定要在菜单项中使用的图像,但这现在在表单中的链接类型标签页中指定,并存储在 params "menu_image" 字段中。
- template_style_id – 在表单中输入的模板样式的 id
- component_id – 与该菜单项相关组件的 id
- parent_id – 菜单项树中的父级 id
- component – 相关组件的名称,如“com_contact”
- tree – 数组,获取树中到达该菜单项的菜单项 id。如果该菜单项的 ID 为 789,父级 ID 为 456,祖父母 ID 为 123,其中祖父母处于最上层菜单(即其父级为根节点),那么返回的 tree 将为数组(“123”、“456”、“789”)。
- query – query 参数的关联数组,在表单的“链接”字段中显示。例如对于指向单个文章的菜单项,此形式为:数组(“option”=>“com_content”、“view”=>“article”、“id”=>“123”)。
菜单项的所有其他属性均存储在数据库中的 params 字段中,并使用 getParams()
方法进行访问。这些数量过多且变化多样,无法在此处全部指定。以下显示两个示例
$params = $menuitem->getParams();
$displayed = $params->get("menu_show");
$show_tags = $params->get("show_tags");
$displayed
变量将保存一个布尔值,具体取决于此菜单项是否应在菜单中显示或隐藏,这对应于表单的“链接类型”选项卡中“在菜单中显示”字段的设置。
$show_tags
变量将保存一个布尔值,用于定义是否显示与正在显示的项目关联的标签。但此字段的存在取决于菜单项指向的网页上显示的内容。如果它是文章或联系方式,则与此相关并可能会设置,但如果它是指向搜索表单或搜索结果的链接,则与此无关,并且不会设置。
其中一些参数(例如那些在菜单项编辑表单的“链接类型”选项卡中定义的参数)可能会针对一般菜单项进行定义,但存储的具体字段取决于所选的菜单项类型(即上述属性列表中的 type
属性)。若要查找这些内容,请在以下位置下的 Joomla 代码中查找:administrator/components/com_menus/forms/item_<type>.xml
,将 <type>
替换为上述 type
之一。这些 xml 文件定义了“菜单:编辑项目”表单的一部分,您可以在其中找到存储在数据库中 params json 字符串中的属性名称,并通过 getParams()->get()
方法以编程方式进行访问。
其他参数与通过此菜单项导航到的组件相关,并且包含与该组件的输出如何在此特定网页上显示相关的属性。要查找这些内容,请找到保存该特定页面的布局文件的文件夹中的 .xml 文件。例如,对于显示单个联系方式的页面,请在 components/com_contact/tmpl/contact/
中查找。
获取单个菜单项
除了上面介绍的用于筛选菜单项的机制,还有一些方法可以让你直接获得某些菜单项。
激活菜单项
站点的激活菜单项关系到 Joomla 用于确定页面展示的菜单项(例如,使用为菜单项定义的模板样式)。要找到该菜单项,请使用
use Joomla\CMS\Factory;
$app = Factory::getApplication();
$sitemenu = $app->getMenu();
$activeMenuitem = $sitemenu->getActive();
然后,你可以按上述说明获取此菜单项的属性和参数。
但是,请注意,在某些情况下未设置激活菜单项(当获得 /component/com_xxx 形式的 SEF 网址时)。
默认菜单项
例如,要查找某个语言的默认菜单项,请使用
$menuitem = $sitemenu->getItem($itemid);
(当你查看管理员后端的菜单项列表时,这正是带有国家/地区标志的菜单项。)
设置菜单项
例如,你可以使用以下代码设置菜单项属性和参数
$menuitem->setParams($params) //set the params values
$sitemenu->setActive($itemid) // set the active menu item
或者通过简单地向菜单项 public 属性分配不同的值。但是,这些更改不会保存到数据库中,只会持续处理当前 HTTP 请求的时间。
示例模块代码
下面是简单 Joomla 模块的代码,你可以安装并运行此代码以演示如何使用菜单项 API 功能。
在 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>";
}
}
将 mod_sample_menu
目录压缩为 mod_sample_menu.zip
。
在 Joomla 管理员中,转到“安装扩展”,然后通过“上传包文件”选项卡选择此 zip 文件以安装此示例菜单模块。
编辑该模块使其可见(在“模块”页面中单击它),然后
- 设其状态为“已发布”
- 为其选择一个页面位置以显示模块
- 在菜单分配选项卡中,指定模块应显示的页面
当访问某个网站页面时,你应在选定的位置看到该模块,模块应显示
- 当前激活菜单项的
Itemid
, - 已使用当前语言的一组菜单项相关属性,
- param 中的一些属性(显示菜单项是否隐藏以及与菜单项关联的任何图像)。
您可以通过添加 URL 参数(例如 ?menulanguage=fr-FR
)使其显示其他语言的属性和参数。