Menu and Menuitems API Guide

From Joomla! Documentation

Introduction

This is one of a series of API Guides, which aim to help you understand how to use the Joomla APIs through providing detailed explanations and sample code which you can easily install and run.

In Joomla a Menu is the set of navigation links you can have as a main menu (eg at the top of your site) or subsidiary menu (eg in the footer). Each of the individual navigation links is a Menuitem.

Within an overall Menu structure you can have a "submenu". This isn't implemented as a Joomla Menu construct, but rather as a set of Menuitems below a parent Menuitem. The Joomla Menuitems are thus implemented in an ordered tree structure, specifically using the Nested Set model.

This guide explains the Joomla API around the Menu/Menuitem area, and includes sample module code which you can install on your site as a demonstration of the capabilities.

Basic Operations

There isn't a Joomla API to enable you to get the set of Menus on the system, so if you really do need these then your only recourse is to read the data from the menu_types table directly using a SQL query. But you can find from the Menuitem structure described below the Menu to which that Menuitem belongs, and find all the Menuitems for a particular Menu.

When the Joomla application starts up in response to an HTTP request arriving at a Joomla site, it builds up a big structure containing lots of things which it realises will likely be needed during the process of working out what will be displayed on the web page. Within this structure it includes all the menuitems which may be needed. To get at this structure do:

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

The $sitemenu structure will have entries for all the menuitems (plus access to a lot of other information besides, but which doesn't concern us).

To get at the individual menuitems we apply a filter to $sitemenu using getItems() to select the particular menuitems we're interested in. To obtain an array of all the menuitems use a blank filter:

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

To obtain an array of all the menuitems which are in the "mainmenu" menu use:

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

The above gives all the menuitems within the "mainmenu" menu, including those in submenus. To access just the menuitems which are in the topmost or first submenu level of the "mainmenu" menu use:

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

To filter the specific menuitems you want, you pass an array of properties (from the list in the next section) and an array of corresponding values which those properties should have.

Unpublished menuitems are not returned. They're not included within the $sitemenu structure.

Note that there isn't an equivalent method to get the menuitems on the administrator back-end, as the equivalent structure to $sitemenu above isn't populated with the admin menu structure. If you wanted to access the menu details you would have to read and interpret the appropriate records from the database.

Properties and Parameters

The following are available as public properties of the Menuitem class. Most of these are shown in the first tab ("Details") of the "Menus: Edit Item" form when you're editing a menu item within the back end. Once you have a Menuitem object you can access the properties directly, as shown below.

$menuitems = $sitemenu->getItems(array(), array()); 
foreach ($menuitems as $menuitem)
{
	echo "Itemid: {$menuitem->id}";
}
  • id – this is the id of the menuitem. In Joomla code it's usually referred to as the Itemid, probably to distinguish it from the id of eg an article (as both often appear in URLs when not using SEF URLs)
  • menutype – this identifies the Menu which the menuitem belongs to. It's a unique identifier Menu Type which you assign to a menu
  • title – what will be displayed when the menu item is shown on the menu (called the "Menu Title" in the form).
  • alias – the segment of the URL when using SEF URLs
  • note – the optional note shown on the form
  • route – the section of the SEF URL which gets to this menu item. Eg if the alias of this menu item is "me", the alias of its parent is "dad", and of its grandparent (at the top level of the menu) is "gran" then the route returned is "gran/dad/me".
  • link – the link shown in the Link field of the form
  • type – usually this will be "component", and the link will point to component functionality in Joomla. But it may also be one of the following, when the Menu Item Type selected is one of the System Links:
    • "heading" – Menu Heading – a heading for the parent of submenu items
    • "alias" – Menu Item Alias – an alias to another menu item
    • "separator" – Separator – a text string (eg dashes) to separate items in a menu
    • "url" – URL – a link to an external URL.
  • level – the level within the menuitem tree. The "root" entry at the base of the tree is level "0", menu items at the top level in a menu have level "1", first submenu level "2", etc.
  • language – the language code eg "es-ES"
  • browserNav – the value associated with the option entered in the Target Window field of the form. Generally this means the following;
    • 0 – Parent – the link opens in the same tab
    • 1 – New Window with Navigation – the link opens in a new tab
    • 2 – New Window without Navigation – the link opens in a new window
  • access – the id of the AccessLevel assigned to this menuitem. When you use this API it checks the logged on user and returns only those menuitems which this user is permitted to view.
  • home – whether or not this is a home page ("Default Page") for the site or language.
  • img – this doesn't seem to be used any more. You can specify an image to be used in the menuitem, but this is now specified in the Link Type tab in the form, and stored in the params "menu_image" field.
  • template_style_id – the id of the Template Style entered in the form
  • component_id – the id of the component associated with this menuitem
  • parent_id – the id of the parent in the menuitem tree
  • component – the name of the associated component, eg "com_contact"
  • tree – an array of the menuitem ids getting to this menuitem in the tree. If this menuitem has id 789, its parent id 456 and grandparent 123, where the grandparent is on the topmost menu (ie its parent is the root node), then tree returned will be an array ("123", "456", "789").
  • query – an associative array of the query parameters shown in the Link field on the form. Eg for a menuitem pointing to a single article this will be of the form: array("option" => "com_content", "view" => "article", "id" => "123").

All the other attributes of the menuitem are stored in the params field in the database and accessed using the getParams() method. These are too many and varied to specify completely here. Two examples are shown below:

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

The $displayed variable will hold a boolean depending on whether this menuitem should be shown in the menu or hidden, corresponding to the setting of the "Display in Menu" field in the Link Type tab in the form.

The $show_tags variable will hold a boolean defining whether or not to show tags associated with the item being displayed. However the presence of this field will depend on what is being presented on the web page which the menu item points to. If it's an article or contact then it's relevant and may be set, but if it's a link to a Search Form or Search Results then it isn't relevant and will not be set.

Some of these parameters (eg those defined in the Link Type tab of the menu item edit form) may be defined for menu items in general, although the specific fields stored depend on the Menu Item Type selected (ie type property in the list of properties above). To find these look in the Joomla code under administrator/components/com_menus/model/form/item_???.xml, replacing ??? by the type. These xml files provide definitions of parts of the "Menus: Edit Item" form, and you can find in them the name of the attribute which is stored in the params json string in the database, and accessed programmatically via the getParams()->get() method.

Other parameters are related to the component which is navigated to via this menu item, and contain attributes which related to how the output of that component is displayed on that particular web page. To find these locate the .xml file in the folder where the layout file for that particular page is held. For example, for a page displaying a single contact look in components/com_contact/contact/tmpl. (See the Joomla Component MVC Tutorial step Adding a variable request in the menu type for an example showing how components define the options to be shown against menu items).

Getting Individual Menuitems

As well as the mechanisms described above for filtering down to the menuitem(s) you want, there are some methods available to get directly to certain menuitems.

Active Menuitem

The active menuitem of a site web page relates to the menuitem which Joomla is using to determine the presentation of that page (eg using the Template Style defined for the menuitem). To find this use:

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

You can then get the properties and parameters of this menuitem as described above.

However, note that there are unusual cases where (in Joomla 3.x at least) the active menuitem is not set. You can show this by configuring your site as described below and using the sample module code included at the end of this page which outputs the active menuitem Itemid.

Set up your site as an international site (eg using the multi-language installation option) and ensure you've got the menu switcher module being displayed. Then create eg

  • a contact "John" with language "English"
  • a contact "Jean" with language "French"
  • associate together these 2 contacts via the Contact Associations feature
  • an "english" menu which contains a menuitem with language "English" pointing to the contact "John"
  • a "french" menu but which has no menuitems relating to Contacts.

Display on your site the English menu, and click on the contact menuitem to show "John". Then click on the French flag in the menu switcher module. This should display the "Jean" contact, but have no active menuitem. Joomla is displaying the French contact (as it's associated to the English one), but can find no menuitem relating to contacts, and so uses a default mechanism for presenting the page, but doesn't have an active menuitem. In general it seems that if you use a menuitem for component A but force it to present component B (by setting the "option" parameter to override the default option associated with a menuitem) then the active menuitem is not set.

Default Menuitem

To find the default menuitem for a language use eg

$lang = "es-ES";      // or $lang = "*" for all languages
$defaultMenuitem = $sitemenu->getDefault($lang);

Menuitem from Itemid

If you wish to find the menuitem associated with a specific id $itemid use:

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

Setting menuitems

You can set menuitem properties and parameters using eg

$menuitem->setParams($params)     //set the params values 

$sitemenu->setActive($itemid)     // set the active menu item

or by simplying assigning different values to the Menuitem public properties. However these changes are not saved to the database and will last only for the duration of handling the current HTTP request.

Sample Module Code

Below is the code for a simple Joomla module which you can install and run to demonstrate use of the Menuitem API functionality. If you are unsure about development and installing a Joomla module then following the tutorial at Creating a simple module will help.

In a folder mod_sample_menu create the following 2 files:

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 Menuitems</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 = Factory::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>";
	}
}

Zip up the mod_sample_menu directory to create mod_sample_menu.zip.

Within your Joomla administrator go to Install Extensions and via the Upload Package File tab select this zip file to install this sample menu module.

Make this module visible by editing it (click on it within the Modules page) then:

  1. making its status Published
  2. selecting a position on the page for it to be shown
  3. on the menu assignment tab specify the pages it should appear on

When you visit a site web page then you should see the module in your selected position, and it should show

  • the Itemid of the current active menuitem,
  • a set of properties associated with menuitems having the current language,
  • a couple of attributes from the params (displaying if the menuitem is hidden, and any image associated with a menuitem).

You can get it to display the properties and parameters for other languages by adding a URL parameter like ?menulanguage=fr-FR.