Это не расширение Joomla, конечно, но, тем не менее, авторское решение
форумчанина форумчан!
Часто бывает надо получить из таблицы связей категорий вида «id_категории - id_родительской» - массив с деревом всех подкатегорий.
Это бывает актуально как для всех категорий (целое дерево), так и для отдельных категорий (одна из веток) - все её подкатегории, всех уровней.
В общем, оформил в виде класса. И потом коллективно переделали/доработали.
После определения класса достаточно двух строчек кода, чтобы получить нужное дерево или ветку
Работает быстро за счёт того, что, в отличие от некоторых других решений, делает всего 1 sql запрос.
Один раз получает таблицу связей, а потом на её основе строит нужное дерево.
В метод getTable заложил реализацию для категорий VirtueMart. Как понимаете, несложной адаптацией запроса можно использовать это с любым расширением, использующим хранение связей категории в виде «id_категории - id_родительской».
Кроме того, при создании объекта класса можно просто передать результаты запроса к своей таблице в параметре, тогда он не будет выполнять свой внутренний запрос.
Пример использования:
$tree = new JFTree();
// дочерние для cat_id=55, включая её id
$sub_cat_list_string = $tree->get_children_list_string(55);
// родители для 367 (в виде массива), не включая её id
$parent_list_array = $tree->get_parents_list(367, false);
unset($tree);
Согласитесь, удобно )
Так вот, код класса (сложенный совместными усилиями):
<?php
/**
* JFTree
* build categories tree
*
* @authors joomlaforum.ru
* @return subcategories tree all levels
*
* @example of usage:
* $tree = new JFTree(); // tree object for DB query results from function getTable()
* $a = new JFTree($results_db_query_loadObjectList); // tree object for custom DB query results with parent_id, child_id
* $b = $tree->get_branch(); // tree with children of root category
* $c = $tree->get_branch(55); // tree with children of category id=55
* $d = $tree->get_children_list(); // list (array) with all children of root category
* $e = $tree->get_children_list(55); // list (array) with all children of category id 55 and itself id
* $f = $tree->get_children_list(55, false); // list (array) with all children of category id 55 (without itself id)
* $g = $tree->get_children_list_string(55); // comma-separated list with all children of category id 55 and itself id
* $h = $tree->get_children_list_string(55, false); // comma-separated list with all children of category id 55 *
* NEW get_parents_list & get_parents_list_string
* $i = $tree->get_subcats_lists_for_all_cats(); // array with all cat_id in indexes and subcats lists in values
* unset($tree);
*/
class JFTree
{
public $tree = array();
public $parents = array();
function __construct($table = array())
{
if (empty($tree)) {
if (empty($table)) $table = $this->getTable();
foreach ($table as $item) {
if (empty($item->parent_id)) $item->parent_id = 0; // may be NULL and other
if (!isset($this->tree[$item->parent_id])) $this->tree[$item->parent_id] = array();
if (!isset($this->tree[$item->child_id])) $this->tree[$item->child_id] = array();
$this->tree[$item->parent_id][$item->child_id] = & $this->tree[$item->child_id];
if (!isset($this->parents[$item->parent_id])) $this->parents[$item->parent_id] = array();
if (!isset($this->parents[$item->child_id])) $this->parents[$item->child_id] = array();
$this->parents[$item->child_id][$item->parent_id] = & $this->parents[$item->parent_id];
}
}
}
private function getTable()
{
$db = JFactory::getDbo();
$query = '
SELECT category_parent_id AS parent_id, category_child_id AS child_id
FROM #__virtuemart_category_categories';
$db->setQuery($query);
return $db->loadObjectList();
}
public function get_branch($parent_id = 0)
{
return isset($this->tree[$parent_id]) ? $this->tree[$parent_id] : false;
}
public function get_children_list($cat_id = 0, $with_it = true)
{
$list = array();
if (preg_match_all('|\[(\d+)\]|isU', print_r($this->get_branch($cat_id), true), $pregs)) {
$list = $pregs[1];
}
if ($with_it && $cat_id != 0) array_unshift($list, $cat_id);
return $list;
}
public function get_children_list_string($cat_id = 0, $with_it = true)
{
$list = $this->get_children_list($cat_id, $with_it);
return implode(', ', $list);
}
public function get_parents($cat_id = 0)
{
return isset($this->parents[$cat_id]) ? $this->parents[$cat_id] : false;
}
public function get_parents_list($cat_id = 0, $with_it = true, $with_root = false)
{
$list = array();
if (preg_match_all('|\[(\d+)\]|isU', print_r($this->get_parents($cat_id), true), $pregs)) {
$list = $pregs[1];
}
$list = array_reverse($list);
if (!$with_root && $list[0] == 0) {
unset($list[0]);
$list = array_values($list);
}
if ($with_it && $cat_id != 0) $list[] = $cat_id;
return $list;
}
public function get_parents_list_string($cat_id = 0, $with_it = true, $with_root = false)
{
$list = $this->get_parents_list($cat_id, $with_it);
return implode(', ', $list);
}
public function get_subcats_lists_for_all_cats($with_root = false)
{
$lists = [];
foreach ($this->tree as $id => $val) {
if (!$with_root && $id == 0) continue;
$list = $this->get_children_list($id);
$lists[$id] = $list;
}
return $lists;
}
}
Принимаю отзывы, предложения и пожелания )