В Cotonti CMF структура категорий хранится в таблице structure и организована в иерархию с помощью следующих полей:
structure_code— уникальный код категорииstructure_path— путь категории, показывающий уровень вложенностиstructure_title— название категорииstructure_area— область структуры (в твоем случае'forums')structure_tpl— шаблон категории (можно использовать для фильтрации)
Как получить иерархический список категорий?
Нужно:
- Получить все категории из базы.
- Разбить их на родительские и дочерние.
- Построить древовидный список для вывода в шаблоне.
<?php
/**
* [BEGIN_COT_EXT]
* Hooks=standalone
* [END_COT_EXT]
*/
// Подключаем необходимые файлы и данные
defined('COT_CODE') or die('Wrong URL');
// Получаем все категории форума
$categories = $db->query("SELECT structure_code, structure_id, structure_title, structure_path FROM $db_structure WHERE structure_area = 'forums' ORDER BY structure_path ASC")->fetchAll();
// Формируем массив иерархии
$category_tree = [];
foreach ($categories as $category) {
$levels = explode('.', trim($category['structure_path'], '.'));
$depth = count($levels); // Определяем уровень вложенности
$category['depth'] = $depth;
$category_tree[] = $category;
}
// Инициализация переменной для выбранных категорий
$selected_categories = [];
// Проверяем, есть ли подписки у пользователя в таблице подписок
if (isset($usr['id'])) {
// Получаем подписки из таблицы $db_subscriptions для текущего пользователя
$subscriptions = $db->query("SELECT cat_forum_subs FROM $db_subscriptions WHERE user_id = ?", [$usr['id']])->fetchAll();
// Преобразуем результат в массив кодов категорий
$selected_categories = array_map(function($row) {
return $row['cat_forum_subs'];
}, $subscriptions);
}
// Если форма отправлена и есть выбранные категории
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['selected_categories'])) {
// Получаем выбранные категории из POST запроса
$selected_categories = $_POST['selected_categories'];
// Сохраняем подписки в таблицу подписок
if (!empty($selected_categories)) {
// Удаляем старые подписки пользователя перед добавлением новых
$db->query("DELETE FROM $db_subscriptions WHERE user_id = ?", [$usr['id']]);
// Добавляем новые подписки
foreach ($selected_categories as $category_id) {
// Пишем новый запрос на добавление подписки
$db->query("INSERT INTO {$db_subscriptions} (user_id, cat_forum_subs, created_at) VALUES (?, ?, ?)",
[$usr['id'], $category_id, time()]);
}
}
}
// Загрузка шаблона
$t = new XTemplate(cot_tplfile('subscriptions', 'plug'));
// Отображаем категории в виде дерева
foreach ($category_tree as $category) {
$t->assign([
'CATEGORY_CODE' => $category['structure_code'], // Код категории
'CATEGORY_ID' => $category['structure_id'], // ID категории
'CATEGORY_TITLE' => str_repeat(' ', $category['depth'] - 1) . $category['structure_title'], // Отступ для вложенности
'IS_SELECTED' => in_array($category['structure_code'], $selected_categories) ? 'checked' : '' // Проверяем, выбрана ли категория
]);
$t->parse('MAIN.CATEGORY');
}
Как это работает?
- Получаем категории, сортируем по
structure_path, чтобы родительские категории были первыми. - Определяем уровень вложенности с помощью
structure_path. Если путь001.002.003, значит категория третьего уровня. - Добавляем отступ перед названием категории (
str_repeat(' ', $depth - 1)), чтобы визуально показать вложенность. - Выводим в шаблоне как древовидный список.
<!-- BEGIN: CATEGORY -->
<li>
<input type="checkbox" name="selected_categories[]" value="{CATEGORY_CODE}" {IS_SELECTED} />
{CATEGORY_TITLE}
</li>
<!-- END: CATEGORY -->
☑ Основной раздел
☐ Подраздел 1
☐ Подраздел 2
☐ Вложенный подраздел