Я написал модуль категорий VirtueMart (
http://joomlaforum.ru/index.php/topic,109669.0.html)
Там есть опция Исключить категории. Так же хочу сделать опцию Вывести Подкатегорию по id
Делал на основе мод_мэйнменю. Работает так: Выборка id, parent_id, other_columns, from ... where id not in (1,3,4)
Полученный результат ввиде массива цикличным перебором перегоняется в объект типа JMenuTree(код писал выше)
Вот как объявлен класс, и еще JMenuNode
* Main Menu Tree Class.
*
* @package Joomla
* @subpackage Menus
* @since 1.5
*/
class JMenuTree extends JTree
{
/**
* Node/Id Hash for quickly handling node additions to the tree.
*/
var $_nodeHash = array();
/**
* Menu parameters
*/
var $_params = null;
/**
* Menu parameters
*/
var $_buffer = null;
function __construct(&$params)
{
$this->_params =& $params;
$this->_root = new JMenuNode(0, 'ROOT');
$this->_nodeHash[0] =& $this->_root;
$this->_current =& $this->_root;
}
function addNode(&$params, $item)
{
// Get menu item data
$data = $this->_getItemData($params, $item);
// Create the node and add it
$node = new JMenuNode($item->id, $item->name, $item->access, $data);
if (isset($item->mid)) {
$nid = $item->mid;
} else {
$nid = $item->id;
}
$this->_nodeHash[$nid] =& $node;
$this->_current =& $this->_nodeHash[$item->parent];
if ($item->type == 'menulink' && !empty($item->query['Itemid'])) {
$node->mid = $item->query['Itemid'];
}
if ($this->_current) {
$this->addChild($node, true);
} else {
// sanity check
JError::raiseError( 500, 'Orphan Error. Could not find parent for Item '.$item->id );
}
}
function toXML()
{
.............
}
function _getLevelXML($depth)
{
........
}
function _getItemData(&$params, $item)
{
.............
}
}
/**
* Main Menu Tree Node Class.
*
* @package Joomla
* @subpackage Menus
* @since 1.5
*/
class JMenuNode extends JNode
{
/**
* Node Title
*/
var $title = null;
/**
* Node Link
*/
var $link = null;
/**
* CSS Class for node
*/
var $class = null;
function __construct($id, $title, $access = null, $link = null, $class = null)
{
$this->id = $id;
$this->title = $title;
$this->access = $access;
$this->link = $link;
$this->class = $class;
}
}
Что меня не устраивает:
1)мы делаем выборку "повисших" категорий, тоесть тех, чьи родители в списке исключений. А ведь они нахер не здались нам
2)мы не можем загрузить из базы определенную ветвь . Мы вынуждены грузить все записи, строить дерево из них и только потом можем вырвать нужную ветвь. это очень херово, особенно когда есть 10 000 категорий, а нам нужна только одна, с пятью подкатегориями.
В общем я порылся в литературе, читал про деревья и все такое. При такой модели без рекурсии не обойтись. Тоесть либо делаем рекурсию на PHP, с кучей запросов в бд, либо пишем хранимую процедуру(кстати в мускуле такая фича есть хоть?)
Другие варианты - только другие модели, например nested sets(или както так), но переписывать весь вирт я не собираюс))
Но всетаки я думаю что в челом вариант описанный в шапке темы в целом более рациональный , как ты думаешь?
Да, в конкретных случаях это лишнее, делать два запроса, строить два дерева...Но в общем случае я думаю это лучше.
Например, у нас 1 000 категорий. верхнего уровня - 5, модуль работает по принципу меню жумлы - кликаешь по категории - она раскрывается(в новой странице) А теперь оценка обоих способов. Текущий способ сделает выборку всех 10 000( с описаниями, картинками, датами и тд) далее, построит дерево из 10 000 узлов, далее обрежет все ненужные узлы, оставив 5 штук.
Второй вариант будет работать так: выборка 10 000 категорий, но только айдишники. Построение дерева из айдишников. Выборка 5 категорий(с описанием и тд) Построение дерева из 5 категорий(думаю на основе уже построенного по айди)
Какой оптимальней будет? И еще. нормально ли будет если в запросе будет множество из 9999 чисел? ну типа where id in (1,2,3,4,..,9999)