- Введение
- Categories
- Свойства CategoryNode
- Методы get CategoryNode
- Методы set CategoryNode
- Пример кода модуля
Введение.
API Joomla Categories и CategoryNode позволяют получить доступ к данным категорий Joomla. Диаграмма ниже иллюстрирует, как классы категорий Joomla соотносятся со структурами базы данных.
Таблица Categories Joomla разбита на "разделы", по одному разделу для каждого компонента, который использует категории. (Здесь "разделы" используется в свободном смысле, не связанным, например, с техническим термином "раздел базы данных"). Внутри каждого раздела записи категорий хранятся в древовидной структуре, но всегда связаны с одним и тем же компонентом - например, у вас не может быть категории com_content
, которая имеет в качестве родителя категорию com_contact
. В корне дерева находится единственный корневой узел системы, который является родителем всех записей категорий верхнего уровня компонентов.
Каждая запись компонента, связанная с категорией, содержит id
записи категории (в качестве внешнего ключа), а все атрибуты категории хранятся в записи категории в таблице Categories
. (Показано на диаграмме на примере com_contact
).
Есть 2 класса Joomla (показаны желтым цветом), которые предоставляют API для доступа к данным категории:
- Categories - Это относится к разделу в таблице
Categories
. Сначала необходимо указать, к какому разделу нужно получить доступ, создав объектCategories
и передав имя компонента в качестве параметра конструктору. - CategoryNode - Относится к отдельной записи Category. Как только создан объект
Categories
, можно получить доступ к объектамCategoryNode
в этом разделе.
В своем коде можно получить доступ к данным категории для нескольких компонентов, создав несколько экземпляров Categories
, по одному для каждого компонента/раздела.
Categories.
Чтобы получить доступ к множеству категорий для com_content, используйте:
use Joomla\CMS\Categories\Categories;
$extension = "content";
$categories = Categories::getInstance($extension);
// Вышеуказанное заменяет старый формат $categories = JCategories::getInstance($extension);
$categoryNodes = $categories->get(12); // возвращает узел категории для категории с id=12
Обратите внимание, что при работе с API Categories у вас нет обычного префикса "com_
" для расширений, имеющих категории в Joomla.
Можно использовать ассоциативный массив опций в качестве второго параметра статического метода Categories getInstance()
. Ключами этого массива являются:
- "
access
" - если этоtrue
(или какое-то значение, которое равнозначно true в PHP), то будут возвращены только те категории, к просмотру которых имеет доступ текущий пользователь. Еслиfalse
, то будут возвращены все категории, независимо от того, имеет ли текущий пользователь доступ к их просмотру или нет. По умолчанию используется значениеtrue
. - "
published
" - если это значение равно1
(целое число один), то будут возвращены только те категории, состояние публикации которых равно1
(т.е. 'published'). В противном случае будут возвращены категории с любым состоянием. Значение по умолчанию равно1
, что означает, что будут возвращены только "опубликованные" категории. - "
countItems
" - если это значение равно1
(целое число один), то при возврате категорий Joomla будет определять для каждой записи категории, сколько элементов расширения связано с этой категорией (по умолчанию подсчет элементов не производится). Для этого Joomla будет делать SQLJOIN
с таблицей расширений,WHERE
полеid
категории в этой таблице совпадает, иCOUNT
экземпляров "ключевого" поля в этой таблице. Joomla необходимо знать, как называются эти таблицы и поля, и они могут быть указаны в опциях массива ниже. - "
table
" - имя таблицы расширения. По умолчанию отсутствует, поэтому вы должны указать его, если используете "countItems
". - "
field
" - имя поля в таблице расширения, которое содержит идентификатор категории (по умолчанию "catid
"). - "
key
" - имя ключевого поля в таблице расширения, по которому выполняется SQLCOUNT
(по умолчанию 'id
'). - "
statefield
" - имя поля в таблице расширения, которое хранит опубликованный статус записи (по умолчанию 'state
'). Если Joomla возвращает только опубликованные категории (как определено опцией "published
", описанной выше), то она будет пересчитывать только опубликованные элементы в таблице расширения. (Обратите внимание, что для параметра "access
" аналогичное действие НЕ выполняется - любое поле Access в таблице расширения игнорируется).
Примеры:
$categories = Categories::getInstance("content", array("access" => false, "published" => 0));
Возвращаемые узлы категории не будут ограничены Access или состоянием Published.
$categories = Categories::getInstance("helloworld", array("countItems" => 1, "table" => "helloworld", "statefield" => "published"));
Узлы категорий компонента "helloworld" будут включать количество связанных записей в таблице "helloworld", где состояние публикации хранится в поле под названием "published
".
Метод get()
Categories принимает в качестве первого параметра id
записи категории, которая должна быть считана из базы данных, и возвращает вызывающей стороне соответствующий объект CategoryNode
. Если id
не указан, то метод возвращает объект CategoryNode
, относящийся к системной записи ROOT
вершины дерева категорий в базе данных.
Функция get()
фактически считывает из базы данных все записи категории, относящиеся к корневой записи категории (что позволяет определить путь категории, описанный ниже), а также все записи-потомки запрашиваемой записи категории. Затем они сохраняются локально, чтобы последующие вызовы для получения данных для любого из этих потомков могли быть выполнены путем возврата данных из этого кэша, а не путем выполнения еще одного запроса к базе данных.
Однако если второй параметр $forceload
имеет значение true
, то запрос будет обработан путем повторного запроса к базе данных, а не с использованием кэшированных записей.
На многоязычном сайте возвращаемые категории будут ограничены категориями текущего языка или языка *
(для всех). Аналогично, любой подсчет элементов в таблице расширений будет ограничиваться элементами текущего языка или языка *
, и Joomla будет считать, что язык хранится в поле под названием "language
" (нельзя переопределить, как называется это языковое поле).
Свойства CategoryNode.
Объектом, полученным в результате вызова метода get($id)
Categories, будет объект CategoryNode
, относящийся к категории с идентификатором $id
. Если при вызове get()
используется значение по умолчанию 'root
', то для получения массива объектов CategoryNode
для нужного расширения необходимо выполнить последующий вызов getChildren()
, например:
use Joomla\CMS\Categories\Categories;
use Joomla\CMS\Categories\CategoryNode;
$categories = Categories::getInstance("content");
$rootNode = $categories->get();
$categoryNodes = $rootNode->getChildren();
Как только создан объект CategoryNode
, можно получить доступ к свойствам этого объекта, как определено в определении API, и они в основном связаны с данными категорий, видимых в формах администратора Joomla. Свойства, смысл которых достаточно ясен, ниже не описываются, но приведен список тех, смысл которых может быть не совсем очевиден.
asset_id
- если администратор определил ACL для отдельной категории, то этоid
записи в таблицеasset
, где хранятся эти ACL.parent_id
,lft
,rgt
,level
- эти поля относятся к положению категории в дереве категорий, которое реализуется с помощью модели Nested Set.- Значения
lft
иrgt
реализованы в соответствии с требованиями модели, parent_id
- этоid
родительской записи в таблице категорий (НЕ в таблице asset - это опечатка в коде Joomla), аlevel
- это:0
для корневого узла,1
для тех записей, чей родитель является корневым узлом,2
для следующего уровня потомков- и т.д.
- Значения
extension
- на этот раз присутствует префикс "com_
".numitems
- количество записей в таблице расширений, которые связаны с данной категориейchildrennumitems
- этот параметр не определен - не пытайтесь его использовать!slug
- это то, что Joomla традиционно отображает как часть URL, когда отображаются SEF URL. Он имеет видid:alias
, например,3:uncategorised
.assets
- этот параметр не определен - не пытайтесь его использовать!
Методы get CategoryNode.
Ряд методов get
CategoryNode позволяет получить доступ к другим объектам CategoryNode в дереве:
getChildren(boolean $recursive = false)
- возвращает массив непосредственных потомков, или массив всех потомков, если
$recursive = true
.
- возвращает массив непосредственных потомков, или массив всех потомков, если
getParent()
- возвращает родительский узел CategoryNode
getSibling(boolean $right = true)
- возвращает соседний CategoryNode справа, или слева, если
$right = false
.
- возвращает соседний CategoryNode справа, или слева, если
Ряд методов get
возвращает свойства объекта CategoryNode
getAuthor(boolean $modified_user = false)
- возвращает объект
User
, связанный с пользователем, который создал категорию, или пользователя, который последний раз изменял его, если$modified_user = true
- возвращает объект
getMetadata()
- возвращает объект реестра Joomla, содержащий метаданные категории (json структура)
getParams()
- возвращает объект реестра Joomla, содержащий параметры категории (json структура)
getNumItems(boolean $recursive = false)
- возвращает количество записей в таблице расширения, относящихся к данной категории. Если
$recursive = true
, то это общее количество записей, связанных с этой категорией и всеми потомками этой категории.
- возвращает количество записей в таблице расширения, относящихся к данной категории. Если
getPath()
- возвращает массив ссылок, идущих от корня дерева категорий вниз по дереву к этой категории.
- Например, если эта категория имеет
id
9 иalias
"dog", ее родитель имеетid
6 иalias
"mammal", а предок (непосредственно под корнем) имеетid
3 иalias
"animal", тоgetPath()
вернетarray(3 => "3:animal", 6 => "6:mammal", 9 => "9:dog")
.
- Например, если эта категория имеет
- возвращает массив ссылок, идущих от корня дерева категорий вниз по дереву к этой категории.
Обратите внимание, что hasParent()
включает родителя, являющегося корневым узлом, так что вызов этого метода всегда будет возвращать true
, если вы не вызываете его на корневом узле.
Методы set CategoryNode.
Существует ряд методов set
в API CategoryNode, но они в основном используются функционалом категорий Joomla для настройки объектов CategoryNode на основе данных, полученных из базы данных. Вызов одного из этих методов не сохраняет данные в базе данных, например, вы не можете использовать setParent()
, чтобы переназначить запись категории под другого родителя категории в базе данных.
Пример кода модуля.
Ниже приведен код простого модуля Joomla, который можно установить и запустить для демонстрации использования функций API Categories и CategoryNode. Если при разработке и установке модуля Joomla нет уверенности, то здесь может помочь руководство по созданию простого модуля.
В папке mod_sample_categories
необходимо создать следующие 2 файла:
mod_sample_categories.xml
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
<name>Categories demo</name>
<version>1.0.1</version>
<description>Код, демонстрирующий использование API Joomla, связанных с Категориями</description>
<files>
<filename module="mod_sample_categories">mod_sample_categories.php</filename>
</files>
</extension>
mod_sample_categories.php
<?php
defined('_JEXEC') or die('Кыш! Кыш!');
use Joomla\CMS\Factory;
use Joomla\CMS\Categories\Categories;
use Joomla\CMS\Categories\CategoryNode;
$app = Factory::getApplication();
$input = $app->input;
$ext = $input->get('categoryextension', "Content", "STRING");
$tab = $input->get('categorytable', "Content", "STRING");
echo "Getting {$ext} categories and using {$tab} table<br>";
echo "-------------<br>";
$categories = Categories::getInstance($ext, array("table" => "Content", "countItems" => 1, "access" => false));
$cat0 = $categories->get('root');
$cats = $cat0->getChildren(true);
foreach ($cats as $cat)
{
echo "Category {$cat->id}, title: {$cat->title}<br>";
echo "Level: {$cat->level}, parent id: {$cat->parent_id}<br>";
echo "Numitems {$cat->getNumitems()}, including descendants: {$cat->getNumitems(true)}<br>";
var_dump($cat->getPath());
echo "-------------<br>";
}
$ext2 = $input->get('option', "", "STRING");
$catid = $input->get('catid', 0, "INT");
$view = $input->get('view', "", "STRING");
$id = $input->get('id', 0, "INT");
if ($ext2 && (strtolower(substr($ext2, 0, 4)) == "com_") && ($catid || (strtolower($view) == "category" && $id)))
{
$ext2 = substr($ext2, 4);
$categories2 = Categories::getInstance($ext2, array("access" => false));
$categoryId = $catid ? $catid : $id;
echo "<br>Getting $ext2 category $categoryId<br>";
$cat2 = $categories2->get($categoryId);
if ($cat2)
{
echo "Category {$cat2->id}, title: {$cat2->title}<br>";
}
}
Заархивируйте каталог mod_sample_categories
, чтобы создать файл mod_sample_categories.zip
.
В админке Joomla перейдите в раздел Установка расширений и на вкладке Загрузить файл пакета выберите этот zip файл для установки модуля sample categories.
Сделайте этот модуль видимым, отредактировав его (нажмите на него на странице Модули), затем:
- установите его статус Опубликован
- выберите позицию на странице для его отображения
- на вкладке Назначить меню укажите страницы, на которых он должен отображаться.
При заходе на страницу сайта модуль должен отображаться в выбранной позиции, при этом он должен показывать набор категорий com_content
в базе данных и для каждой категории:
id
иtitle
level
в дереве категорий иid
родителя- количество статей, для которых установлена данная категория, и количество статей, для которых установлена данная категория или ее дочерние категории
var_dump
возвращаемого значенияgetPath()
категории.
Можно получить категории для других компонентов, добавив к URL параметры categoryextension
и categorytable
, например: ...&categoryextension=contact&categorytable=contact_details
для получения категорий com_contact
. Обратите внимание, что если при попытке получить категории компонента, который не является одним из базовых компонентов Joomla, возможно, потребуется указать имена полей компонента и т.д. в options
вызова Categories::getInstance()
, как описано выше.
Код также пытается определить, относится ли отображаемая страница к категории, проверяя, есть ли в URL параметр catid
, или если параметр view
установлен в 'category
'. В этом случае он показывает id
и title
соответствующей категории. Очевидно, что это может работать не во всех случаях.
Перевод с английского официальной документации Joomla 3:
https://docs.joomla.org/Categories_and_CategoryNodes_API_Guide
Заберите ссылку на статью к себе, чтобы потом легко её найти!
Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
Не надо себя сдерживать! ;)