Блог переехал, статья тут: http://mkdev.ru/?p=5
среда, 11 ноября 2009 г.
вторник, 1 сентября 2009 г.
Проблемы с sfDoctrineTreePlugin
Здесь было описание проблемы. Описание съели опера и WYSIWYG-редактор =\
В общем, дело обстояло так. В нынешнем проекте необходимо иметь список вложенных категорий. Symfony с ORM Doctrine позволяют это сделать практически без напрягов. Структура каталога категорий - вложенные множества (nested sets), о них и о других иерархических структурах данных можно почитать, например, здесь. В Доктрине есть встроенные средства для доступа и хранения таких структур. Для отображения данных нашел плагин к Symfony - sfDoctrineTreePlugin. С точки зрения интерфейса - красивый, кроссбраузерный (работает даже в Opera), но немного не доделанный.
Объясню. В исходной таблице с данными порядка 70 записей. При попытке отображения дерева данным плагином имеем большие тормоза. Открываем лог и видим ~300 запросов к базе. Непорядок. Пришлось лезть в код плагина и ковыряться. После небольших правок итог - 4 запроса. Если кому интересно или я вдруг забуду, опишу решение:
Необходима правка кода шаблона sfDoctrineTreePlugin/modules/sfDoctrineTree/templates/_nested_set_list.php:
Код здесь. Проблема была в вызовах в цикле вида $record->getNode()->getLevel(), которые я заменил на $record->getLevel().
В общем, дело обстояло так. В нынешнем проекте необходимо иметь список вложенных категорий. Symfony с ORM Doctrine позволяют это сделать практически без напрягов. Структура каталога категорий - вложенные множества (nested sets), о них и о других иерархических структурах данных можно почитать, например, здесь. В Доктрине есть встроенные средства для доступа и хранения таких структур. Для отображения данных нашел плагин к Symfony - sfDoctrineTreePlugin. С точки зрения интерфейса - красивый, кроссбраузерный (работает даже в Opera), но немного не доделанный.
Объясню. В исходной таблице с данными порядка 70 записей. При попытке отображения дерева данным плагином имеем большие тормоза. Открываем лог и видим ~300 запросов к базе. Непорядок. Пришлось лезть в код плагина и ковыряться. После небольших правок итог - 4 запроса. Если кому интересно или я вдруг забуду, опишу решение:
Необходима правка кода шаблона sfDoctrineTreePlugin/modules/sfDoctrineTree/templates/_nested_set_list.php:
<?php use_helper('Javascript', 'DoctrineTree'); ?>
<?php if( isset($records) && is_object($records) && $records->count() > 0 ): ?>
<ul id="dhtmlgoodies_tree2" class="dhtmlgoodies_tree">
<?php
$prevLevel = 0;
$noRootAttr = " noDrag='true' noSiblings='true' noDelete='true'";
if ($no_root_rename) {
$noRootAttr .= " noRename='true'";
}
if (isset($options['noAdd']) && $options['noAdd']) {
$noRootAttr .= " noAdd='true'";
}
$nodeNoAttr = $options->count() > 0 ? _tag_options($options) : null;
foreach($records AS $record):
$currentLevel = $record->getLevel();
$noAttr = $currentLevel == 0 ? $noRootAttr : $nodeNoAttr;
$recordIdentifier = $record->identifier();
foreach ($recordIdentifier as $obj) {
$identifier[] = $obj;
}
if($prevLevel > 0 && $currentLevel == $prevLevel) {
echo '</li>';
}
if($currentLevel > $prevLevel) {
echo '<ul>';
}
elseif ($currentLevel < $prevLevel) {
echo str_repeat('</ul></li>', $prevLevel - $currentLevel);
}
?>
<li id ="node<?php echo $identifier[0] ?>" <?php echo $noAttr ?>>
<?php
$partial = $link_partial ? $link_partial : 'sfDoctrineTree/link';
include_partial($partial, array('record' => $record, 'model' => $model, 'field' => $field, 'root' => $root, 'identifier' => $identifier[0]));
if ($currentLevel == 0) {
echo image_tag('/sfDoctrineTreePlugin/images/indicator.gif', array('style' => 'padding:0pt 5px;display:none;vertical-align:middle;', 'id' => 'doctrine_tree_indicator'));
}
$prevLevel = $currentLevel;
endforeach;
?>
</li>
</ul>
<?php endif; ?>
Код здесь. Проблема была в вызовах в цикле вида $record->getNode()->getLevel(), которые я заменил на $record->getLevel().
Мысли и фреймворки
Месяц назад начал новый проект на пятой версии PHP. Фреймворк - Symfony 1.2 . Производительность не самая высокая, но привлекает грамотный код, расширяемость, удобство.
Первое время изучал фреймворк. К тому моменту имел опыт работы с CakePHP, Zend Framework и самописными фрейворками и CMS. Было сложно уйти от простоты кейка, так сказать, cake-way. Кейк позволяет много вольностей в отличие от симфони.
Позволю сделать небольшое отступление. Многие фреймворки, с которыми я работал, реализуют паттер MVC (Model-View-Controller). Он дает хорошие результаты, чтобы не просто отделить код от отображения, но и для того чтобы отделить часть кода отвечающего за бизнес-логику от кода управления системой.
Многие современные фреймворки имеют подсистемы генерации кода, управляющего системой (админ-генераторы). Их основная проблема - слабые возможности штатного изменения (кастомизации). Также много проблем доставляют не самая лучшая реализация генерации частей системы отвечающих за работу с моделями, обладающими большим количеством связей. В частности моделей со связями типа "многие ко многим".
Но это все лирика. Основные сложности, с которыми сталкиваются новички в Symfony, это обилие документации. К сожалению, в документации не описаны многие возможности. Приходится обращаться к поисковым системам.
Также к минусам можно отнести высокий порог вхождения. Мне, как не самому слабому программисту, с опытом разработки веб-приложений около трех лет, было довольно сложно понять философию Symfony. Не могу и сейчас сказать, что я понял его до конца :) . Будем стараться.
PS. Несколько сумбурный пост. В голове куча мыслей. Попытался их хоть как-то упорядочить.
Первое время изучал фреймворк. К тому моменту имел опыт работы с CakePHP, Zend Framework и самописными фрейворками и CMS. Было сложно уйти от простоты кейка, так сказать, cake-way. Кейк позволяет много вольностей в отличие от симфони.
Позволю сделать небольшое отступление. Многие фреймворки, с которыми я работал, реализуют паттер MVC (Model-View-Controller). Он дает хорошие результаты, чтобы не просто отделить код от отображения, но и для того чтобы отделить часть кода отвечающего за бизнес-логику от кода управления системой.
Многие современные фреймворки имеют подсистемы генерации кода, управляющего системой (админ-генераторы). Их основная проблема - слабые возможности штатного изменения (кастомизации). Также много проблем доставляют не самая лучшая реализация генерации частей системы отвечающих за работу с моделями, обладающими большим количеством связей. В частности моделей со связями типа "многие ко многим".
Но это все лирика. Основные сложности, с которыми сталкиваются новички в Symfony, это обилие документации. К сожалению, в документации не описаны многие возможности. Приходится обращаться к поисковым системам.
Также к минусам можно отнести высокий порог вхождения. Мне, как не самому слабому программисту, с опытом разработки веб-приложений около трех лет, было довольно сложно понять философию Symfony. Не могу и сейчас сказать, что я понял его до конца :) . Будем стараться.
PS. Несколько сумбурный пост. В голове куча мыслей. Попытался их хоть как-то упорядочить.
Еще один блог в дополнение к прочим)
Много лет провел в Сети и только сейчас понял необходимость блога. Буду вести блог для себя. Публиковать свои наработки и заметки. Тематика любая.
PS Надеюсь блог не загнется) Буду стараться.
Подписаться на:
Сообщения (Atom)