Как программно создать материал с настраиваемыми полями на PHP

  • Дмитрий Рекун

Рассмотрим, как программно создать материал в Joomla с настраиваемыми полями, используя Joomla API. Не забудем и про полный обзор стандартных полей материала, которые мы можем использовать при создании материала.

Для удобства, весь код, который мы рассмотрим в рамках данного материала, расположен в репозитории на GitHub. Он оформлен в виде CLI расширения (скрипта), то есть полностью рабочий и при желании, вы можете протестировать его работу. Настоятельно рекомендуется ознакомиться с кодом перед дальнейшим чтением, так как далее мы будем ссылаться на его составляющие.

Начнём мы наш путь с метода createArticle().

Создание материала

Для того, чтобы программно создать материал, мы воспользуемся API компонентов ядра. Это даёт на уверенность в том, что материал будет создан корректно.

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

Как правило, основная бизнес логика расположена в моделях компонентов и com_content не исключение. За создание материала отвечает класс модели ContentModelArticle, который расположен по пути /administrator/components/com_content/models.

Вот как выглядит подключение этого класса в Joomla 3:

// Задаём константу расположения компонента.
define('JPATH_COMPONENT', JPATH_ADMINISTRATOR . '/components/com_content');

// Добавляем путь поиска классов модели.
BaseDatabaseModel::addIncludePath(JPATH_COMPONENT . '/models/', 'ContentModel');

// Инициализируем объект модели класса ContentModelArticle.
$model = BaseDatabaseModel::getInstance('Article', 'ContentModel');

В Joomla 4 и выше не требуется задавать константы или подключать классы. Вместо этого достаточно "загрузить" компонент и создать модель через MVC фабрику. Это удобно, так как нужно знать только название компонента:

$mvcFactory = $this->app->bootComponent('com_content')->getMVCFactory();
$model = $mvcFactory->createModel('Article', 'Administrator', ['ignore_request' => true]);

Далее мы создаём массив полей материала:

$article = [
	'id'        => 0,
	'title'     => 'Article Title', // заголовок
	'alias'     => '', // пустой, чтобы не было notice
    'introtext' => 'Article Text', // текст
	'catid'     => 2, // категория
	'state'     => 0, // состояние публикации
	'language'  => '*', // язык
	'access'    => $this->app->get('access', 1) // уровень доступа
];

Это минимально необходимый набор полей, который требуется для корректного создания материала. Ниже вы найдете полный обзор всех полей, а сейчас взглянем на ту часть кода, которая обрабатывает массив полей и создаёт материал:

// Получаем форму материала, чтобы провалидировать данные.
$form = $model->getForm($article, false);

if (!$form)
{
	throw new \RuntimeException('Error getting form: ' . $model->getError());
}

// Валидируем данные.
if (!$model->validate($form, $article))
{
	throw new \RuntimeException('Error validating article: ' . $model->getError());
}

// Эмулируем действие сохранения.
$this->app->input->set('task', 'save');

// Сохраняем (создаём) материал.
if (!$model->save($article))
{
	throw new \RuntimeException('Error saving article: ' . $model->getError());
}

Посмотрев на этот код, скорее всего у вас возник вопрос - а зачем эмулировать действие сохранения? Да, можно обойтись и без этого, но этот кусочек кода даёт команду модели корректно обработать массив, в котором не указан alias материала. Если убрать этот код, то придётся самим написать эту обработку. Но зачем изобретать что-то своё?

Второй момент на который стоит обратить внимание, это $this->app. Мы выполняем обращение к приложению, которое доступно в плагинах через свойство $app. Вне области плагинов обращение к приложению выполняется через Factory::getApplication().

В конце мы сохраняем настриваемые поля материала:

$this->saveArticleFields($model->getItem()->id);

Сохранение настраиваемых полей

Для сохранения настраиваемых полей мы опять же воспользуемся API компонентов ядра. За настраиваемые поля в Joomla отвечает компонента com_fields. За сохранение поля отвечает класс модели FieldsModelField, который расположен по пути /administrator/components/com_fields/models.

Для того, чтобы связать поля с материалом, нам необходим его ID, который мы получили на предыдущем шаге после сохранения материала: $model->getItem()->id, и передали в метод saveArticleFields() в качестве параметра.

Метод saveArticleFields() начинается с подключения класса FieldsModelField:

// Регистрируем класс FieldsHelper.
\JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

// Добавляем путь поиска классов модели.
BaseDatabaseModel::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/models', 'FieldsModel');

// Инициализируем объект модели класса FieldsModelField.
$model = BaseDatabaseModel::getInstance('Field', 'FieldsModel', array('ignore_request' => true));

Код выше актуален для Joomla 3. А вот в Joomla 4 и выше, как уже упоминалось ранее, для создания модели используем MVC фабрику:

$model = $this->app->bootComponent('com_fields')->getMVCFactory()->createModel('Field', 'Administrator', ['ignore_request' => true]);

Затем формируем массив полей:

$fields = [
	1 => 'Text', // текстовое поле
	3 => ['Value 2', 'Value 1'], // список
	4 => [2, 1] // чекбоксы
];

Массив должен состоять из пары ID поля => значение поля.

Там, где поле подразумевает наличие нескольких значений одновременно (например список или чекбокс с атрибутом multiple), значения должны передаваться в формате массива. Порядок элементов массива не важен. Главное, чтобы совпадали значения.

После того, как массив полей сформирован, мы можем его сохранить:

foreach ($fields as $key => $value)
{
	$model->setFieldValue($key, $articleId, $value);
}

Как мы видим, для сохранения нам понадобились: ID поля, ID материала и значение поля. Дальше API всё делает за нас, изобретать особо не приходится.

Обзор полей материала

Итак, у нас уже есть всё необходимое, чтобы создать материал. Давайте рассмотрим более детально все стандартные поля материала, которые мы можем использовать при его создании. По сути это всё, что хранится в таблице #__content.

title
Заголовок. Строковое поле.
alias
Алиас. Строковое поле.
introtext
Вступительный текст. Если полный текст не указан в поле fulltext, то для указания текста используется поле introtext.
fulltext
Полный текст. Используется, если заполнено поле introtext.
articletext
Текст материала. Альтернатива для introtext и fulltext. Если текст передаётся с тегом
<hr id="system-readmore" />
то текст автоматически разбивается на introtext и fulltext. В противном случае текст попадает в поле introtext.
catid
ID категории, которой принадлежит материал. Числово поле.
state
Состояние публикации: 0 - не опубликовано; 1 - опубликовано; 2 - в архиве; -2 - в корзине.
featured
Является ли материал избранным: 0 - нет; 1 - да.
access
Уровень доступа материала. Числово поле.
language
Язык материала. Если значение * - принадлежит всем языкам. Либо указываем язык в формате: en-GB, ru-RU и т.п.
created
Дата и время создания материала в формате 0000-00-00 00:00:00. Если не указано, то используются дата и время в момент создания.
created_by
Автор в виде ID пользователя. Числовое поле.
created_by_alias
Алиас автора. Используется вместо имени пользователя при отображении автора. Текстовое поле.
modified
Дата и время изменения материала в формате 0000-00-00 00:00:00. Если не указано, то используется created.
modified_by
Автор изменения в виде ID пользователя. Числовое поле.
publish_up
Дата и время начала публикации материала в формате 0000-00-00 00:00:00.
publish_down
Дата и время окончания публикации материала в формате 0000-00-00 00:00:00.
images
Изображения материала в формате массива. В базе данных хранятся в виде JSON строки:
  • image_intro - изображение вступительного текста
  • float_intro - выравнивание изображения вступительного текста: right - вправо, left - влево, none - без выравнивания
  • image_intro_alt - альтернативный текст изображения вступительного текста
  • image_intro_caption - текст, который будет отображаться под изображением вступительного текста
  • image_fulltext - изображение вступительного текста
  • float_fulltext - выравнивание изображения вступительного текста: right - вправо, left - влево, none - без выравнивания
  • image_fulltext_alt - альтернативный текст изображения вступительного текста
  • image_fulltext_caption - текст, который будет отображаться под изображением вступительного текста
urls
Ссылки материала в формате массива. В базе данных хранятся в виде JSON строки:
  • urla - ссылка A
  • urlatext - текст ссылки A
  • targeta - окно браузера A: 0 - открывать в родительском окне; 1 - открывать в новом окне; 2 - открывать модально
  • urlb - ссылка B
  • urlbtext - текст ссылки B
  • targetb - окно браузера B: 0 - открывать в родительском окне; 1 - открывать в новом окне; 2 - открывать модально
  • urlc - ссылка C
  • urlctext - текст ссылки C
  • targetc - окно браузера C: 0 - открывать в родительском окне; 1 - открывать в новом окне; 2 - открывать модально
attribs
Параметры материала в формате массива. В базе данных хранятся в виде JSON строки:
version
ID версии материала (актуально, если включена версионность). Числовое поле.
metakey
Мета-тег Keywords. Строковое поле.
metadesc
Мета-тег Description. Строковое поле.
metadata
Метаданные в формате массива. В базе данных хранятся в виде JSON строки.
  • robots - мета-тег Robots. Возможные значения index, follow; noindex, follow; index, nofollow; noindex, nofollow
  • author - мета-тег Author. Строковое поле
  • rights - мета-тег Rights. Строковое поле
ordering
Порядковый номер материала. Числовое поле.
note
Примечание. Строковое поле.

Form API CLI

  • Последнее обновление: .

© Joomla для профессионалов. Все права защищены.