Задачи могут быть самые разные: поле аватара для пользователя в com_users, дополнительный таб в форму редактирования материала, поле связи одной сущности с другой и т.д. Сразу оговорюсь, что бывает и "non-Joomla way" - то есть подходы, которые не предполагаются ядром CMS, но при этом и явно не запрещаются. Сейчас речь пойдёт о традиционном.

Наиболее употребимый вариант добавления своего поля или даже формы сводится к 2 простым вещам:

  1. Создать XML файл с нужной формой

  2. На событии onContentPrepareForm плагином добавить свою форму в форму расширения.

Приведу пример из одного давнего проекта - добавление поля с id продаваемых курсов в Moodle в карточку товара компонента интернет-магазина RadicalMart Express.

Структура плагина.
Структура плагина.

XML файл с формой

Кто сильно заинтересуется - можно почитать официальную документацию Joomla How Forms Work. В XML мы описываем филдсеты и поля, а также с помощью структуры создаем имена для полей.

<?xml version="1.0" encoding="utf-8"?>
<form>
    <fieldset name="wtradicalmartexpresstomoodle"
              label="PLG_WTRADICALMARTEXPRESSTOMOODLE_FIELDSET_LABEL"
              description="PLG_WTRADICALMARTEXPRESSTOMOODLE_FIELDSET_DESC">
        <fields name="plugins">
            <field addfieldprefix="Webtolk\JMoodle\Fields"
                   type="moodleinfo"
                   name="moodleinfo"/>
            <field addfieldprefix="Webtolk\JMoodle\Fields"
                   type="courseslist"
                   name="course_ids"
                   multiple="true"
                   layout="joomla.form.field.list-fancy-select"
                   filter="intarray"
                   label="PLG_WTRADICALMARTEXPRESSTOMOODLE_COURSE_ID"
                   description="PLG_WTRADICALMARTEXPRESSTOMOODLE_COURSE_ID_DESC"/>
        </fields>
    </fieldset>
</form>

Тег <fieldset> - это отображаемый таб формы. У него есть системное имя name, label - название таба для людей. Description - дополнительная информация в начале таба.

Вложенность в именах полей формы Joomla Form

В форме карточки товара RadicalMart Express для различной кастомной информации зарезервировано имя plugins, куда, собственно говоря, плагины и могут помещать всякую нужную им информацию. Поэтому мы создаем секцию <fields name="plugins">. а в ней уже помещаем описание нашего select, который по REST API получает список доступных курсов из стоящего рядом Moodle. В HTML-коде имя поля будет jform[plugins][course_ids][]. Если мы уберём секцию <fields>, то имя поля было бы jform[course_ids][]. Если нам нужно добавить уровень вложенности с именем level2, то в XML файле формы мы добавляем ещё один <fields name="level2">:

<?xml version="1.0" encoding="utf-8"?>
<form>
    <fieldset name="wtradicalmartexpresstomoodle"
              label="PLG_WTRADICALMARTEXPRESSTOMOODLE_FIELDSET_LABEL"
              description="PLG_WTRADICALMARTEXPRESSTOMOODLE_FIELDSET_DESC">
        <fields name="plugins">
            <fields name="level2">
                <field addfieldprefix="Webtolk\JMoodle\Fields"
                       type="courseslist"
                       name="course_ids"
                       multiple="true"
                       layout="joomla.form.field.list-fancy-select"
                       filter="intarray"
                       label="PLG_WTRADICALMARTEXPRESSTOMOODLE_COURSE_ID"
                       description="PLG_WTRADICALMARTEXPRESSTOMOODLE_COURSE_ID_DESC"/>
            </fields>
        </fields>
    </fieldset>
</form>

Дальше <field> описывает поле, которое может быть как стандартным, так и пользовательским: из 3d-party компонента, библиотеки или ваше собственно из вашего же плагина. Достаточно указать namespace этого поля. А имя поля = имени класса + "Field". В нашем примере это CourseslistField.

Стандартные поля Joomla Form: официальная документация старая, официальная документация новая.

Добавление поля Joomla Form плагином

В примере кода ниже представлен не весь плагин Joomla целиком, но только один важный для нас метод - onContentPrepareForm. Через это событие проходят все формы Joomla, поэтому нам важно проверять имя формы и добавлять свои поля только в нужную. Имя формы Joomla обычно строится по принципу com_component.entity.

<?php
use Joomla\CMS\Form\Form;
use Joomla\Event\Event;

public function onContentPrepareForm(Event $event): void
{
	$form     = $event->getArgument(0);
	$formName = $form->getName();
	// Проверяем имя формы, чтобы не добавить таб в материалы или ещё куда-нибудь
	if ($formName === 'com_radicalmart_express.product')
	{
		Form::addFormPath(JPATH_SITE . '/plugins/system/wtradicalmartexpresstomoodle/src/Xmlform');
		// fields - это имя файла в указанной папке - fields.xml
		$form->loadFile('fields', false);
		// грузим языковые константы для формы
		$lang      = $this->getApplication()->getLanguage();
		$extension = 'plg_system_wtradicalmartexpresstomoodle';
		$base_dir  = JPATH_ADMINISTRATOR;
		$reload    = true;
		$lang->load($extension, $base_dir, $lang->getTag(), $reload);
	}
}

Обработка данных формы

Если компонент предусматривает поля в базе для сторонних данных, то возможно вам ничего и не придется дописывать, а всю работу сделает за вас модель компонента. Если же ваши данные хранятся не в стандартной таблице базы данных компонента, а в своей, то в плагине нужно использовать событие onContentPrepareData, то есть ДО onContentPrepareForm . В нём вы делаете запрос в свою таблицу и оперируете данными. Это событие вызывается ДО подготовки формы. То есть Joomla сначала собирает все данные, потом собирает форму, затем биндит данные в форму. Для сохранения данных в свою таблицу можно использовать события onContentBeforeSave или onContentAfterSave. Также у компонентов могут быть свои собственные события для плагинов, вызываемые в процессе работы компонента.

Ну и всё... Теперь чтобы добавить ещё одно поле в карточку товара нам достаточно описать поле в XML-форме.

В хабе Joomla публиковал немало уже статей о разных видах плагинов. В них можно подчерпнуть информацию о структуре плагинов, логике и практике использования.

Полезные ресурсы

Ресурсы сообщества:

Telegram:

Комментарии (2)


  1. VitaliyNekrasov
    25.10.2024 09:41

    А методами Joomla можно добавить поле в нужный subform?


    1. sergeytolkachyov Автор
      25.10.2024 09:41

      Можно. Это более сложный случай, но возможный. Можно также не делать физический XML-файл формы, а полностью и собирать его на PHP с помощью SimpleXML. Тоже нередко встречающиеся случаи.