nopox

Рейтинг
5
Регистрация
15.08.2007

Бяка способ. На каждый узел дерева по одному запросу - жирновато, как мне кажется. Всё дерево целиком можно получить одним запросом, а потом рекурсией (которая и в этом примере используется, правда, довольно бездарно) его перестроить...

Навскидку код будет выглядеть примерно так. Пишу навскидку прямо в форуме, без проверки. Надеюсь, ошибок не наляпаю, но будьте к ним готовы :). Впрочем, понять суть метода, думаю, можно.


define('NODE_BEGINS', '<ul>'); // html-код, который будет вставляться в начале узла
define('NODE_ENDS', '</url>'); // html-код, который будет вставляться в начале узла
define('LEAF_BEGINS', '<li>'); // html-код, который будет вставляться в начале листа ветви
define('LEAF_ENDS', '</li>'); // html-код, который будет вставляться в конце ветви

$res = mysql_query('SELECT id, parent_id, title FROM catalogue ');
$tree = array();

while ($row = mysql_fetch_object($res)) {
$tree[$row->parent_id][$row->id] = $row->title;
}

print _recurse($tree);

/**
* Рекурсивно обходит дерево и возвращает HTML
*
* @param array $tree
* @param integer $parent_id
* @return string
*/
function _recurse($tree, $parent_id = 0)
{
$code = NODE_BEGINS;

foreach ($tree as $id => $root) {
if ($parent_id != $id) {
continue;
}

if (count($root)) {
foreach ($root as $key => $title){
$code.= LEAF_BEGINS;

// Нужна ссылка? Измените строчку ниже. Как - догадайтесь сами ;)
$code.= $title;

if (count($tree[$key])) {
$code.= _recurse($tree, $key);
}

$code.= LEAF_ENDS;
}
}
}
$code.= NODE_ENDS;
return $code;
}

Не знаю, будет ли работать на PHP4, меня провидение миловало, не пришлось с ним работать :) Я просто попытался максимально примитизировать идею, поэтому код получился грязноватым. Если кому интересно, могу "правильно" (т.е. с ООП :)) переписать этот же код на PHP5.

Слава Шевцов:
Перл настолько суров, что читает с диска 2 Гб за две секунды? 🙄

Думаю, не в суровости перла дело, а в его умении грамотно и оптимально использовать ресурсы системы. А PHP для CLI слабоват, да

Слава Шевцов:
Можно я эту цитату всегда буду приводить PHP-шникам, когда они будут необоснованно нападать на Перл в холивар?

Можно и даже нужно ;). Я сам, как перловщик с 8-летним стажем пытаюсь это донести до своих собратьев по перу ;). До кого-то даже удаётся достучаться :).

Слава Шевцов:
Время чтения с диска либо гиг в секунду, либо не учитывалось. Обычно 2Гб/60Мб/сек ~ 35 сек 🙄

Не знаю, как так получилось... Быть может, система кеширует часто изменяемые файлы, держит в памяти их потоки; быть может, дело в том, что винты SCSI. Может, обе причины. Как бы то ни было, замеры производились не наручными часами, а запуском парсеров через time ;)

Слава Шевцов:
Часто парсите такие логи? 🙄

Постоянно :) Не всегда HTTP (случается и за сквидом следить, к примеру), не всегда двухгигабайтные (бывает и больше, но обычно меньше :)), но очень большие - постоянно.

Слава Шевцов:
PHP работает достаточно быстро. В любом случае строковыми функцими быстрее написать и отладить парсер, чем вспоминать Перл с его трудночитабельным кодом и регулярками. То есть код получится дешевле.

Код у перла нечитабелен только в том случае, если его писать так, как пишут большинство перловщиков. Процедурное программирование, использование пакетов не более чем неймспейсы, названия переменных и подпрограмм а-ля $hz, a(), b(), hz(). Как бы парадоксально это ни звучало, код на перле может быть очень красивым. :)

Слава Шевцов:
Хотя если двухгигабайтный лог надо парсить каждый день, то можно и о Перле подумать. Или о С++ 🚬

...или воспользоваться tail, sed, grep и средствами операционной системы. ;)

Но перл, тем не менее сбрасывать со счётов я бы не стал.

А Вы проверьте, попробуйте (я про загнать большой файл в файл) ;)

Только как человек, в своё время наступавший на эти грабли, не советую играться на сервере, где крутятся важные проекты.

Виктория Родочинская:
все зависит от реализации!
какие маски регекспов или используете ли вы вообще регекспы...(они тормозные... жуть бррр...)
а не от того, что это перл или пхп....

Разумеется, всё зависит от реализации. Регекспы, разумеется, спользовались, какой же без них парсинг. А насчёт их тормознутости - не совсем верно. Да, разумеется, строковое сравнение быстрее регулярного. Но тут есть один ньюанс: это справедливо для одного сравнения паттерна.

Все последующие регулярные совпадения будут обработаны существенно быстрее (PCRE кеширует выражения), чем первое, поэтому при обработке больших объёмов текста регулярные выражения могут быть существенно быстрее строкового поиска...

Виктория Родочинская:
П.П.С можно пример пхп и перл скрипта.... уж очень слабо верится по поводу скорости разбора на перле...

Конкретно тех скриптов нет и чего там выпарсилось, я уже и не помню. Поэкспериментируйте :)

Вот перловый скрипт:

#!/usr/bin/perl


open LOG, '<', 'access.log';
while (my $line = <LOG>) {
if ($line =~ /(GoogleBot|Slurp)/i) {
# do something
}
}
close LOG;

Вот на php:


#!/usr/local/bin/php
<?php
$fp = fopen('access.log', 'r');
while ($line = fgets($fp)) {
if (preg_match('/(GoogleBot|Slurp)/i', $line)) {
# do something
}
}
?>

Попробуйте поменять паттерны на свои, добавить какую-то логику... В общем, пофантазируйте ;)

Skom:
По дефолту, пхп 8 мегами памяти ограничен.
Почему-то мне кажется, что если ему сказать memory_limit 500M, то он будет парсить поменьше, чем 3 минуты :D
Конечно перл будет почти всегда быстрее. Он же для регекспов и сделан.
Просто из-за сиюминутной задачи вникать в особенности работы с перлом не всегда необходимо.

Неверно Вам кажется :)

Зачем загонять огромный файл в память, когда можно открыть поток и просто читать его построчно? Для запоминания текущей позиции курсора в потоке нужно гораздо меньше памяти, чем 8М.

Использовать php для парсинга большого объёма текста не очень желательно. Скорее даже очень нежелательно. Нет, я помимаю, что и микроскопом можно забивать гвозди, но для этого существуют гораздо более подходящие средства.

Для примера:двухигабайтный лог апача перлом парсился уть больше двух секунд. А пхп скрипел почти три минуты =)

Не знаю, если честно, где Вы общие моменты у MZZ и CI нашли... Разве что оба - MVC-фреймворки ;)

Zhilinsky:
Ха ! Разделение прав доступа надо :-D

На всякий случай: в Zend Framework есть пакет Zend_Acl, который с этой задачей весьма и весьма справляется. Из автономных готовых решений phpGACL, но он требует ADODB.

Есть отечественная разработка - CMF\CMS MZZ (http://mzz.ru), в которой тоже есть неплохая реализация ACL. Если потратить некоторое время на изучение и поход, то сможет помочь.

Zhilinsky:
Есть некий скрипт, работающий с базой - смотреть таблички, менять значения. Нужно авторизовать пользователя и подсунуть ему нужную таблицу в базе данных.

Скаффолдинг? :)

Работа с базой - пара страниц кода, а как представлю, что всё остальное надо писать - выть хочеццо =(

Всё остальное писать придётся в любом случае :). Но фреймворки позволяют свести нудятину к минимуму.

Проще всего через wget в режиме зеркалирования :)

А потом уже локальную копию и парсить можно. По желанию.

12 3
Всего: 26