Есть 3 менюшки для каталога:
При публикации одного документа (товара) нужно обновлять все 3 менюшки. Если делать это на djemscript, то трижды придется дергать базу что бы вынуть одни и те же данные.
На времени публикации это явно не здорово сказывается.
Чтобы минимизировать временные задержки и максимизировать удобство работы клиента будем строить все эти менюшки на php (но к базе, конечно же, лишний раз обращаться не будем).
Корень дерева:
<?php Class Catalogue_Tree extends Catalogue_Tree_NodeBase { /* * Узлы дерева */ private $nodes = array(); /* * Конструктор */ public function __construct() { {{ подсчет товаров }} <foreach name="x" path="main.rus.catalogue.*" where="_type == 203"> <set 'count_' ~ <foreach[x]._parent_id> = <var['count_' ~ <foreach[x]._parent_id>]> + 1> </foreach> {{ построение дерева }} <foreach name="x" path="main.rus.catalogue.*" where="_type in '201,202'" sort="_gsort"> $this->nodes[<foreach[x]._id>] = new Catalogue_Tree_Node( array( 'id' => <foreach[x]._id>, 'type' => <foreach[x]._type>, 'url' => '<foreach[x]._url.js>', 'name' => '<foreach[x]._name>', 'total' => <if <foreach[x]._type> == 202><var['count_' ~ <foreach[x]._id>]><else>null</if> ), <if <foreach[x]._parent_id> == <['main.rus.catalogue']._id>> null <else> $this->nodes[<foreach[x]._parent_id>] </if> ); <if <foreach[x]._parent_id> != <['main.rus.catalogue']._id>> $this->nodes[<foreach[x]._parent_id>]->addChild($this->nodes[<foreach[x]._id>]); <else> $this->children[] = $this->nodes[<foreach[x]._id>]; </if> </foreach> } /* * Деструктор */ public function __descruct() { $this->nodes = array(); $this->children = array(); $this->parent = null; } /* * Вывести структуру */ public function structure() { foreach($this->children as $root) { print "\n" . $root->name; print $root->structure(); } } } ?>
Узел дерева:
<?php Class Catalogue_Tree_Node extends Catalogue_Tree_NodeBase { /* * Данные ноды */ private $data; /* * Родитель */ private $parent; /* * Конструктор */ public function __construct($data, $parent) { $this->data = $data; $this->parent = $parent; } /* * Деструктор */ public function __descruct() { $this->children = array(); $this->parent = null; $this->data = array(); } /* * Добавить ребенка */ public function addChild($item) { $this->children[] = $item; } /* * Количество элементов в разделе */ public function size() { if($this->data['total'] !== null) { return $this->data['total']; } $size = 0; foreach($this->children as $child) { $size += $child->size(); } return $size; } /* * Структура */ public function structure($level = 1) { foreach($this->children as $child) { print "\n"; for($i = 0; $i<=$level; $i++) { print " "; } print $child->name . ' - ' . $child->size(); print $child->structure($level + 1); } } /* * Геттер */ public function __get($k = '') { return isset($this->data[$k]) ? $this->data[$k] : ''; } /* * Построить UL */ public function buildUl($active = array()) { $html = '<ul>'; foreach($this->children as $child) { $html .= '<li><a href="' . $child->url . '">' . $child->name . '</a>'; if($child->hasChildren()) { if(in_array($child->id, $active)) { $html .= $child->buildUl($active); } } else { $html .= ' (' . $child->size() . ')'; } $html .='</li>'; } return $html .= '</ul>'; } } ?>
Общие методы для узлов дерева:
<?php Class Catalogue_Tree_NodeBase implements Iterator { /* * Позиция итератора */ public $iteratorPosition = 0; /* * Дети */ protected $children = array(); /* * Есть ли дети */ public function hasChildren() { return count($this->children); } /* * Iterator: Возвращает итератор на первый элемент */ function rewind() { $this->iteratorPosition = 0; } /* * Iterator: Возвращает текущий элемент */ function current() { return $this->children[$this->iteratorPosition]; } /* * Iterator: Возвращает ключ текущего элемента */ function key() { return $this->iteratorPosition; } /* * Iterator: Переходит к следующему элементу */ function next() { ++$this->iteratorPosition; } /* * Iterator: Проверка корректности позиции */ function valid() { return isset($this->children[$this->iteratorPosition]); } } ?>
Ну и дальше уже строим менюшки средствами php. Например:
<table width="100%"> <tr><?php $catalogueTree = new Catalogue_Tree(); foreach($catalogueTree as $node) { if($node->type == 201) { ?><td class="item_block"> <h5><a href="<?php print $node->url; ?>"><?php print $node->name; ?></a></h5> <ul><?php foreach($node as $subnode) { ?><li><a href="<?php print $subnode->url; ?>"><?php print $subnode->name; ?></a> <span>(<?php print $subnode->size(); ?>)</span></li><?php } ?></ul> </td><?php } } ?></tr> </table>
Таким образом djemscript'ом мы обходим каталог всего 2 раза (подсчет
количества товаров и получение разделов каталога - отправляем всего 2 SQL
запроса), а не 6 раз. Мелочь, а приятно .
Catalogue_Tree инициализируется за 0.0005 секунды, сильно медленнее от этого
сайт работать не будет