Продумать структуру базы. категории 3-го или 4-го уровня вложенности

123
P
На сайте с 08.02.2016
Offline
23
#11

Мы говорим о построении меню или о чём? category_id, parent_id, name, shortname, picture, bodytext, short_description - хотя бы это можно хранить в одной таблице. Ну и плюс всякие мета-теги, если они не различаются от региона посетителя или еще чего-нибудь. Я не предлагаю свойства товаров (если они к категории привязываются) хранить в той же таблице, это дебилизм же. А у нас никакой разной структурой и не пахнет.

---------- Добавлено 25.09.2018 в 16:19 ----------

miketomlin:
pringlesday, пример запроса «без джоинов» в студию. И структуру таблицы заодно, если она отличается от представленной ТСом.

Я даже больше скажу. Берешь Simpla CMS 1.4 с любого торрента, смотришь содержимое файла Storefront.class.php

Здесь, тебя интересуют две функции:


// Функция возвращает категории товаров, и их подкатегории
function get_categories($parent=0)
{
// Выбираем все категории
$query = sql_placeholder("SELECT * FROM categories WHERE enabled=1 ORDER BY parent, order_num", $parent);
$this->db->query($query);
$temp_categories = $this->db->results();
$categories = Storefront::categories_tree($temp_categories);
return $categories;
}


// Функция возвращает подкатегории
function categories_tree($categories)
{
$tree = array();

// Указатели на узлы дерева
$used_items = array();

$end = false;

// Не кончаем, пока не кончатся категории, или пока ниодну из оставшихся некуда приткнуть
while(!empty($categories) && !$end)
{
$flag = false;
foreach($categories as $k=>$category)
{
if($category->parent == 0)
{
// Добавляем элемент в дерево
$cat = null;
$cat->name = $category->name;
$cat->category_id = $category->category_id;
$cat->url = $category->url;
$category->path[0] = $cat;

$tree[$category->category_id] = $category;
$used_items[$category->category_id] = &$tree[$category->category_id];
unset($categories[$k]);
$flag = true;
}else
{
if($used_items[$category->parent])
{
$cat = null;
$cat->name = $category->name;
$cat->category_id = $category->category_id;
$cat->url = $category->url;

$category->path = $used_items[$category->parent]->path;
$category->path[] = $cat;


$used_items[$category->parent]->subcategories[$category->category_id] = $category;
$used_items[$category->category_id] = &$used_items[$category->parent]->subcategories[$category->category_id];
unset($categories[$k]);
$flag = true;
}
}
}
if(!$flag)
$end = true;
}

$used_items = array_reverse($used_items, true);
foreach($used_items as $k=>$item)
{
$used_items[$item->category_id]->subcats_ids[] = $item->category_id;
if(is_array($used_items[$item->parent]->subcats_ids))
$used_items[$item->parent]->subcats_ids = array_merge($used_items[$item->parent]->subcats_ids, $item->subcats_ids);
else
$used_items[$item->parent]->subcats_ids = $item->subcats_ids;
}
return $tree;
}

Структура таблицы:

Я не топлю за это решение, просто оно подходит для решения задачи, хоть движок очень старый. Однако даже в то время он без всякого кеширования справлялся с каталогами из десятков тысяч товаров. Если нормально проставить индексы, то сотни тысяч.

miketomlin:

P.S. ТС походу подзабил на тему. Видать, конкретно загрузили :) Или сидит втихаря кодит :D

Просто его загрузили сложными терминами, и он забил. Будет дальше сидеть с 2 уровнями вложенности.

---------- Добавлено 25.09.2018 в 16:23 ----------

Вроде бы форум должен нормально экранировать php, но с квадратными скобками накосячил.

S
На сайте с 30.09.2016
Offline
469
#12
pringlesday:
Мы говорим о построении меню или о чём?

Нет. мы говорим не о построении меню, а о построении базы данных.

pringlesday:
// Не кончаем, пока не кончатся категории
Это шедеврально.
Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
lutskboy
На сайте с 22.11.2013
Offline
184
#13

pringlesday,

$query = sql_placeholder("SELECT * FROM categories WHERE enabled=1 ORDER BY parent, order_num", $parent);

ето значит вытащит все поля из таблици категорий?

ви знаете сколько у меня будет строк в такой таблице.?

Миллионы

Пройдитесь по сайтам каталогам автозапчастей и посмотрите их структуру.

Там производителей может быть до 100. у каждого из них до 200 моделей

а у них свои узлы.

P
На сайте с 08.02.2016
Offline
23
#14

Запрос будет приблизительно такой. Строка кода может отличаться. В упомянутом мной движке sql_placeholder используется для защиты от SQL-инъекции. Как будет у вас - никто точно не скажет. Многое зависит от движка. Вообще лучше не делать костыли а использовать те функции, что уже предусмотрены или дорабатывать их.

Russ1an
На сайте с 25.03.2015
Offline
84
#15
ето значит вытащит все поля из таблици категорий?
ви знаете сколько у меня будет строк в такой таблице.?
Миллионы

Подгружайте тогда потомков аяксом, а выбирайте категории 1 уровня.

M
На сайте с 04.12.2013
Offline
223
#16
pringlesday:
Просто его загрузили сложными терминами, и он забил. Будет дальше сидеть с 2 уровнями вложенности.

Зачем влезать, если вы даже не до конца поняли смысл обсуждаемого. Речь шла прежде всего о структуре БД для построения каталога, а не о построении дерева или многоуровневого меню, хотя последнее тоже может понадобиться, что ТС показал выше наглядно. В каталоге прежде всего нужно построение хлебных крошек, вывод дочерних категорий и элементов для тек. уровня иерархии, определяемого адресом запроса. А мой пример с двумя уровнями – это просто частный случай (кстати, если считать конечные элементы, то там получается три уровня, правда, этот уровень я обычно не отражаю в каталожной иерархии адресов, а делаю отдельно /product1 или /products/1). Я там рядом одним предложением описал решение для произвольного уровня вложенности. И даже в послед. посте написал, как можно контролировать уровень вложенности, если тупой пользователь или бот начнет лепить 100-компонентные пути (тебе хочется выполнять основанный на этом запрос к БД? Мне лично нет, т.к. я заранее уверен, что у меня точно не наберется столько уровней, и в конце запроса корневой узел будет многократно присоединять сам к себе во избежание явной ошибки – я обычно в корневом узле специально делаю «петлю»). Еще раз: с учетом конечных элементов ты многократно присоединяешь к таблице этих элементов таблицу категорий; без учета конечных элементов ты многократно присоединяешь к таблице категорий саму себя.

Домены и скрипт для коротких ссылок: https://u75.ru/domains-for-shortcuts
P
На сайте с 08.02.2016
Offline
23
#17
miketomlin:
Зачем влезать, если вы даже не до конца поняли смысл обсуждаемого. Речь шла прежде всего о структуре БД для построения каталога, а не о построении дерева или многоуровневого меню, хотя последнее тоже может понадобиться, что ТС показал выше наглядно...

Вы сами попросили пример запроса. А ТС спросил, подойдёт ли его структура БД для реализации многоуровневого каталога. Я ответил примером, который очень похож на предложенный самим ТС. Если нужно построение хлебных крошек, вывод дочерних категорий и всё такое (сам ТС, кстати, до моего сообщения конкретно об этом не спрашивал), $category->path во втором листинге хранит путь к текущей категории. Все дочерние категории хранятся в $category->subcategories. Если нужно получать текущую категорию со списком подкатегорий (вместо целого каталога), то там есть функция category_by_url($categories, $url). Её листинг приводить не буду. Как я уже сказал, можете сами скачать и глянуть код. Повторюсь, ни с кем спорить не собираюсь. Мне задали вопрос, я ответил и, по-моему, достаточно развёрнуто.

Sitealert:
Это шедеврально.

Либо это проделки тех, кто выкладывает nulled версии, либо такие разрабы. Самому смешно.

M
На сайте с 04.12.2013
Offline
223
#18
pringlesday:
Вы сами попросили пример запроса.

Это было уже после того, как вы «влезли» :)

pringlesday:
А ТС спросил, подойдёт ли его структура БД для реализации многоуровневого каталога.

Не совсем так:


я так понимаю что можно типа так...
но тогда как вытащить
ето ж сколько запросов делать нужно

Ему ответили, что делать нужно один запрос.

---------- Добавлено 26.09.2018 в 12:06 ----------

pringlesday:
сам ТС, кстати, до моего сообщения конкретно об этом не спрашивал
Даже если бы речь была не о каталоге, а о каком-то API по извлечению данных категорий из БД, это были бы его основные ф-ции. Ф-ция, возвращающая все дерево, конечно в нем тоже могла быть, но она бы точно не была основной. API для распределенных систем строятся на др. принципах.
P
На сайте с 08.02.2016
Offline
23
#19

Я влез, ответил на вопрос, привёл пример, причём не самопальный, а из реального движка. Если у ТСа сомнения, он может проверить работоспособность на своей системе как вашего, так и предложенного мной решения. Когда задача подразумевает несколько способов её решить, лучше их все рассмотреть, чтобы оценить трудозатраты и совместимость.

totamon
На сайте с 12.05.2007
Offline
437
#20
lutskboy:
Пройдитесь по сайтам каталогам автозапчастей и посмотрите их структуру.
Там производителей может быть до 100. у каждого из них до 200 моделей
а у них свои узлы.

при чем тут производители и модели? речь шла о категориях... и категорий будет вряд ли больше тыщи-двух, не миллион...

для хранения вашего примера БД достаточно, а как вытаскивать и отображать это другая история, обычно описанная в ТЗ

Домены и хостинг https://8fn.ru/regru | Дедик от 3000р https://8fn.ru/73 | VPS в Москве https://8fn.ru/72 | Лучшие ВПС, ТП огонь, все страны! https://8fn.ru/inferno | ХОСТИНГ №1 РОССИИ https://8fn.ru/beget
123

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий