В данной статье я поделюсь собственным велосипедом, как сделать чтобы в модели Joomla появился дополнительные необходимые поля и чтобы при этом не была утрачена возможность обновлять CMS. Вопрос о возможности добавления полей в модель меню Joomla без правок в ядре появилась у меня при обдумывании подходов к реализации многосайтовости на Joomla. Все тесты производились на версии Joomla 3.9.14. Возможность использования подхода как и отдельного кода из листингов данной статьи на иных версиях CMS Joomla не проверялась.
PHP файлы реализующие модель меню Joomla
Для понимания устройства модели в Joomla 3.9 обратимся к листингам PHP кода следующих файлов:
- /libraries/src/Menu/SiteMenu.php
- /libraries/src/Menu/AbstractMenu.php
- /libraries/src/Menu/MenuItem.php
В файле MenuItem.php находится набор полей каждого элемента(пункта) меню. В файле SiteMenu.php находится метод load который выполняет запрос к базе данных связанный с меню, данный метод приведён в следующем листинге. Кроме запроса информации из базы данных в методе load находится логика по работе с кешем.
Таким образом если требуется добавить поля(переменные к модели данных меню), требуется внести изменения в SQL запрос к базе данных в файле SiteMenu.php, а так же соответственно добавить аналогичные переменные в файле MenuItem.php для этих полей. Кроме этого необходимо добавить поля в таблице базы данных joomprefix_menu.
Переменные модели меню Joomla
В следующем листинге приведён var_dump примера объекта модели меню Joomla тестового сайта созданного на версии CMS Joomla 3.9.14 с одним меню из двух элементов. Указанный объект получается в результате выполнения строчки кода $db->loadObjectList('id','Joomla\\CMS\\Menu\\MenuItem'); которая находится в методе load в файле SiteMenu.php.
Так же приведу пример var_dump массива запроса из базы данных без класса модели меню $db->loadObjectList('id'); он в следующем листинге(данные меню того же сайта что и в листинге выше). Можно заместить что массив данных полученный из базы данных отличается по полям от объектной можели меню.
Для того чтобы из массива в последнем листинге получить массив объектов аналогичный полученному в результате вызова $db->loadObjectList('id','Joomla\\CMS\\Menu\\MenuItem'); можно использовать следующий код.
Не смотря на то что код в листинге выше способствует созданию массива объектов аналогичного вызову $db->loadObjectList('id','Joomla\\CMS\\Menu\\MenuItem') логика получения в одном и другом случаи тем не менее несеолько отличаются. На момент написания текущей статьи я не выяснял как именно обрабатывает метод loadObjectList второй передаваемый параметр(то есть строку 'Joomla\\CMS\\Menu\\MenuItem'), тем не менее если второй параметр указан то метод loadObjectList тем не менее не передаёт конструктору файла MenyItem.php каких либо данных, то есть единственный входящий мараметр указанного конструктора инициализируется по умолчанию как array() то есть пустой массив. В коде же из листинга выше в цикле передаётся массив с данными для каждого элемента мени и затем исходному элементу массива присваивается выхожное значение объекта new \Joomla\CMS\Menu\MenuItem($one); с подставленными в объект данными. Вызов метода loadObjectList с вторым параметром обращается к коснтруктору файла MenuItem.php лишь единожды, а не в колличестве раз равному количеству элементов в меню. Таким образом предположительно что вызов loadObjectList в вторым параметром получает от класса переданного в втором параметре лишь структуру данных, а затем своими внутренними методами применяет к строкам полученным из базы данных например кланированием объекта.
API для работы с menu Joomla
Для того чтобы получить объект активного элемента меню можно использовать код из следующего листинга.
Код из листинга выше возвращает объект класса MenuItem содержащий активный пункт меню. Пример var_dump этого объекта приведен в листинге ниже