API Categories и CategoryNodes в Joomla 3

Руководство по API Categories и CategoryNodes

  1. Введение
  2. Categories
  3. Свойства CategoryNode
  4. Методы get CategoryNode
  5. Методы set CategoryNode
  6. Пример кода модуля


Введение.

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

Диаграмма API Joomla Categories и CategoryNode

Таблица Categories Joomla разбита на "разделы", по одному разделу для каждого компонента, который использует категории. (Здесь "разделы" используется в свободном смысле, не связанным, например, с техническим термином "раздел базы данных"). Внутри каждого раздела записи категорий хранятся в древовидной структуре, но всегда связаны с одним и тем же компонентом - например, у вас не может быть категории com_content, которая имеет в качестве родителя категорию com_contact. В корне дерева находится единственный корневой узел системы, который является родителем всех записей категорий верхнего уровня компонентов.

Каждая запись компонента, связанная с категорией, содержит id записи категории (в качестве внешнего ключа), а все атрибуты категории хранятся в записи категории в таблице Categories. (Показано на диаграмме на примере com_contact).

Есть 2 класса Joomla (показаны желтым цветом), которые предоставляют API для доступа к данным категории:

  1. Categories - Это относится к разделу в таблице Categories. Сначала необходимо указать, к какому разделу нужно получить доступ, создав объект Categories и передав имя компонента в качестве параметра конструктору.
  2. 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 будет делать SQL JOIN с таблицей расширений, WHERE поле id категории в этой таблице совпадает, и COUNT экземпляров "ключевого" поля в этой таблице. Joomla необходимо знать, как называются эти таблицы и поля, и они могут быть указаны в опциях массива ниже.
  • "table" - имя таблицы расширения. По умолчанию отсутствует, поэтому вы должны указать его, если используете "countItems".
  • "field" - имя поля в таблице расширения, которое содержит идентификатор категории (по умолчанию "catid").
  • "key" - имя ключевого поля в таблице расширения, по которому выполняется SQL COUNT (по умолчанию '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.

Ряд методов 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.

Сделайте этот модуль видимым, отредактировав его (нажмите на него на странице Модули), затем:

  1. установите его статус Опубликован
  2. выберите позицию на странице для его отображения
  3. на вкладке Назначить меню укажите страницы, на которых он должен отображаться.

При заходе на страницу сайта модуль должен отображаться в выбранной позиции, при этом он должен показывать набор категорий 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

Заберите ссылку на статью к себе, чтобы потом легко её найти ;)

Выберите, то, чем пользуетесь чаще всего:

Спасибо за внимание, оставайтесь на связи! Ниже ссылка на форум и обсуждение ; )

Войдите чтобы комментировать

Обсудить эту статью

INFO: Вы отправляете сообщение как 'Гость'