Как программно создать материал с настраиваемыми полями на 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
- ссылка Aurlatext
- текст ссылки Atargeta
- окно браузера A:0
- открывать в родительском окне;1
- открывать в новом окне;2
- открывать модальноurlb
- ссылка Burlbtext
- текст ссылки Btargetb
- окно браузера B:0
- открывать в родительском окне;1
- открывать в новом окне;2
- открывать модальноurlc
- ссылка Curlctext
- текст ссылки Ctargetc
- окно браузера 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
- Примечание. Строковое поле.
- Последнее обновление: .