Построение одной ветке от текущего id_cat до самого верхнего.
Помогите пожалуйста с правильным решением!
Интересуют еще примеры для решения этой задачи, т.е. оптимизация, скорость выполнения... Туго у меня с этими ветками и деревьями. У меня получилось так (см. ниже). Входящий идентификатор категории/подкатегории в $id_cat. Если $id_cat = 100, то получим на выходе: Разделы > Раздел 1. Если $id_cat = 102, то получим на выходе: Разделы > Раздел 3 > Раздел 3.1. :thanks:
// Построение одной ветке от текущего id_cat до самого верхнего.
// Пример.
// Разделы > Раздел 3 > Раздел 3.1
/*
id_cat parent_id title
98 0 Разделы
100 98 Раздел 1
101 98 Раздел 3
102 101 Раздел 3.1
106 98 Раздел 2
*/
// Получаем все id_cat и parent_id.
$query = "SELECT `id_cat`, `parent_id` FROM dl_category";
$result = mysql_query($query);
// Все id_cat и parent_id в массив.
while($row = mysql_fetch_assoc($result))
{
$arr_id_cat_all[] = $row['id_cat'];
$arr_parent_id_all[] = $row['parent_id'];
}
mysql_free_result($result);
// Получаем ветку id_cat'ов.
// От текущего id_cat до самого верхнего (до нулевого).
if ($id_cat != '0')
{
$id_cat_tmp = $id_cat;
for ($x = 0; $x < count($arr_id_cat_all); $x++)
{
if ($arr_id_cat_all[$x] == $id_cat_tmp)
{
// id_cat'ы в массив $branch_id_cat[].
$branch_id_cat[] = $id_cat_tmp;
// Родитель.
$id_cat_tmp = $arr_parent_id_all[$x];
if ($id_cat_tmp != '0')
{
// Нет, еще не все.
$x=0;
}
else
{
// Все id_cat'ы уже в массиве,
// в такой последовательности: 54321;
$branch_id_cat[] = $id_cat_tmp;
// Поменять местами 54321 на 12345.
for ($x = count($branch_id_cat) - 1; $x >= 0; $x--)
{
$new_branch_id_cat[] = $branch_id_cat[$x];
}
// Все...
break;
}
}
}
}
else
{
$new_branch_id_cat[] = '0';
}
// Сделать: 1,2,3,4,5
$string_branch = implode(",", $new_branch_id_cat);
|
У вас даже запрос не предполагает выборку именно дерева.
1) Традиционное получение дерева - рекурсия в запросе. 2) Рекурсия, это плохо и ее можно избежать - запрос формируется как подключение таблиц потомков. 3) NESTED SETS - иное описание дерева в базе данных. |
Цитата:
|
laimas!
Если вы еще здесь? Можно где-то почитать об этом: Цитата:
NESTED SETS Многое непонятно... |
Я здесь, но на данный момент нет времени писать много. Позже, и только теоретические выкладки, хотя это не означает, что это гольная теория. )
|
А можно как-то к PHP подключить свой модуль, ну скажем написаный на ассемблере?
Это чтобы решить проблемы связанные с рекурсией. Дополнение. Вот ответ: exec в PHP, читать здесь: http://php.net/manual/ru/function.exec.php и пусть рекурсия вас не пугает. А дальше - есть Си, есть ассемблер... |
Цитата:
РНР язык высокого уровня, но для каждой платформы свой интерпретатор. А Ассемблер вообще привязан к системе команд процессора. Расширения для РНР пишут на С. Рекурсия для выборки дерева, это множество запросов к базе и никаким Ассемблером этого не исправить. Но можно обойтись единственным запросом, но с условием, что на глубину вложения есть ограничение. Если глубина вложения небольшая (например меню сайта, где большая глубина вложения вряд ли уместна), то формируется запрос, который прост по сути - в запросе подключается таблица (в которой хранится дерево) числом равным максимальному уровню вложения минус 1, по условию равенства parent ее записей id предыдущего подключения: SELECT label1.fields, label2.fields, label3.fields, ... FROM table label1 LEFT JOIN table label2 ON label2.parent = label1.id LEFT JOIN table label3 ON label3.parent = label2.id ..... WHERE .... ORDER BY .... где label формируемые псевдонимы подключаемых таблиц и их полей. Результатом запроса будут записи сгруппированные по дереву, которые в цикле можно разобрать формируя html-код меню или иное требуемое. |
Спасибо за информацию.
Насчет ассемблера, Вы не правы... Дополнение. Рекурсию можно отдать через exec программе написаной на си или ассемблере. Вот небольшой (маленький) пример как это выглядет:
echo exec("buildbranch 102", $resultarr);
где buildbranch - программа. 102 - идентификатор, на основе которого нужно построить ветку. Результат вернеться в массив $resultarr. Программа которая написана в самом вверху переписуется на си, если нужно получить максимальную производительность - ее пишут на ассемблере. Это только маленький и неполный пример, как это может быть. Немного компьютерной истории. Процессор 3мГц, гибкий диск 800кб, на нем англо-русский и руско-английский словарь (один символ - один байт, 1024 байта - 1кб). Так вот, суть этой байды... Перевод слов мгновенный. Улыбнитесь! Это ассемблер. :) Ну да ладно. П.С. Что говорят специалисты по поводу ассемблера? "На нем можно одновременно чистить зубы и писять в ведро". |
Цитата:
Дело не в Ассемблере, а в запросах к базе, это вы понимаете? Если писать традиционно, как это и делается, то это будут рекурсивные запросы к базе. От такого третирования базы не спасет не Ассемблер ни что иное. Можно выбрать все скопом, все переложить в массив, а уже рекурсивным на РНР строить ветви. Впрягать сюда еще и Ассемблер, это кошмар. Кроме рекурсии есть еще два подхода, думайте и выбирайте. |
Цитата:
Для этого существуют другие субд! Программа, которая написана вверху, мной была переписана на Си. Что Вам сказать? Цитата:
Метод NESTED SETS, хорош для выбивания денег из любознательных. Я мысленно прохожусь по порядку от 1 до 32 и не мого понять :blink: кто будет обнавлят левый и правый ключ после добавления узла? Тема не раскрыта полностью. Писать автору я не буду, он может денег попросить. :blink: Вот сама программа (см. ниже). Ладно, шутки-шутками, а посуществу, программа написанная на PHP вверху, дохнет на 3000 категорий с десятком подкатегорий, плюс одна подкатегория имеет 30 вложенных подкатегорий. Так вот, на этих 30 подкатегориях время генерации странцы приблизительно 0.45 сек. Что касается Си - скушал и не подавился... Комп древней с установленной ОС FreeBSD. Вот еще мысль: Ассемблер, Си, Js - браузерные шахматы. Правда выиграть у компьютера невозможно...
// Это Си не путать с PHP.
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // exit(1);
#define N 80
//
// Чтение двух столбцов текстового файла в два массива.
// Пример текстового файла:
// ... ...
// 234 560
// 103 789
// 456 232
// ... ...
//
int i = 0, k = 0, j =0 , j_1 = 0, j_2 = 0;
long int current_id_cat, current_id_cat_tmp;
long int array_branch_id_cat[8192];
long int array_new_branch_id_cat[8192];
int main(int argc, char* argv[])
{
// Получаем текущий идентификатор категории.
current_id_cat = atoi(argv[2]);
FILE *file = NULL;
// В argv[1] путь с именем файла идентификаторов.
file = fopen(argv[1], "r");
if(file == NULL)
{
// Ошибка открытия файла.
puts("Error opening file!");
exit(1); // Завершение с кодом ошибки 1.
}
char array_1[8192][N]; // id_cat.
char array_2[8192][N]; // parent_id.
char line[N];
while ( fgets (line, N, file) )
{
j_1 = 0; j_2 = 0; k = 0;
while(1)
{
// Останов, если нет пробела.
if (k > N) break;
// Останов, если найден пробел.
if (line[k] == ' ')break;
{
array_1[i][j_1] = line[k];
}
j_1++;
k++;
}
// Пропустить пробел.
k++;
while(1)
{
// Останов, если нет конца строки.
if (k > N) break;
// Останов, если найден конец сторки.
if (line[k] == '\n')break;
{
array_2[i][j_2] = line[k];
}
j_2++;
k++;
}
i++;
}
fclose(file);
// Решаем вопрос с веткой.
if (current_id_cat != 0)
{
// Находим ветку.
k = 0;
current_id_cat_tmp = current_id_cat;
for (j = 0; j < i; j++)
{
if (atoi(array_1[j]) == current_id_cat_tmp)
{
// id_cat'ы в массив array_branch_id_cat[].
array_branch_id_cat[k] = current_id_cat_tmp;
k++;
// Родитель.
current_id_cat_tmp = atoi(array_2[j]);
if (current_id_cat_tmp != 0)
{
// Нет, ещё не все.
j = 0;
}
else
{
// Все id_cat'ы уже в массиве,
// в такой последовательности: 54321;
array_branch_id_cat[k] = current_id_cat_tmp;
k++;
// Поменять местами 54321 на 12345.
i = 0;
for (j = k-1; j >= 0; j--)
{
array_new_branch_id_cat[i] = array_branch_id_cat[j];
i++;
}
// Вот они.
for (j = 0; j < k; j++)
// В вывод их, PHP потом их заберёт...
printf("%d\n", array_new_branch_id_cat[j]);
// Всё.
break;
}
}
}
}
else
{
// Текущий id_cat равен нулю.
// В вывод...
printf("%d\n", current_id_cat);
}
return 0;
}
П.С. Вы неправильно батон крош... Ну это, ломаете... Надеюсь, админы не удалят мою писанину... |
Цитата:
Цитата:
Если у вас дерево-монстр, С и вперед, кто же вам не дает. Игрушки компьютерные меня не интересуют. ) |
Дополнение.
Вот это: шутки-шутками, нужно взять в кавычки! Вот так это: "шутки-шутками". |
Цитата:
Запрос на MySQL в студию можно? Цитата:
|
Цитата:
Это серьезный архив! |
Цитата:
|
Давайте оставим это.
Я кое-что нашел интерсное в NESTED SETS. Что еще. Категории/подкатегории можно посмотреть в таких форумах как PHPBB, SMF и др. Еще информация (может кому-то пригодится). SMF более шустрый, чем PHPBB... |
Вот нашел ("хохлы" пишут):
https://uk.wikipedia.org/wiki/Модель_вкладених_множин Улыбнитесь :yes: Я вам сейчас карму добавлю... Не получается, пишет вот: Вы должны добавить отзыв кому-то ещё, прежде чем сможете снова добавить его laimas. Жаль. За ангажированный Вы какой-то (сплошная коррупция). Жаль. |
Цитата:
Мои извинения за некоторые вольности. |
Какой-то монолог обо всем на свете.
|
| Часовой пояс GMT +3, время: 23:22. |