Правильно ли я сделал вывод?
PHP:
<?php $host = ‘localhost’; $db = ‘test’; $user = ‘root’; $pass = »; $charset = ‘utf8’; $dsn = «mysql:host=$host; dbname=$db;charset=$charset«; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $pdo = new PDO($dsn, $user, $pass, $opt); $sql = «SELECT * FROM `category`»; $res = $pdo->query($sql)->fetchAll(); echo ‘<ul>’; foreach($res as $key => $val) { $subCat = «SELECT * FROM sub_category WHERE category_id = « . $val[‘id’]; $result = $pdo->query($subCat)->fetchAll(); echo ‘<li>’; echo ‘<a href=»cat-‘.$val[‘id’].‘»>’.$val[‘name’]. ‘</a>’; echo ‘<ul>’; foreach($result as $k => $v) { echo ‘<li><a href=»sub-‘.$v[‘id’].‘»>’ . $v[‘name’] . ‘</a></li>’; } echo ‘</ul>’; echo ‘</li>’; } echo ‘</ul>’;Для каждой категории, сделал отельный запрос, на подкатегорию, это правильный подход?
Если сделать запрос на категории и подкатегории
Код (Text):
SELECT category.id, category.name, sub_category.name FROM category LEFT JOIN sub_category ON sub_category.category_id = category.idТо получится вот такое
1 Программы Антивирусы
1 Программы Запись
1 Программы Интернет
1 Программы Аудио
2 Фильмы Боевики
2 Фильмы Фантастика
2 Фильмы УжастикиИ такой массив с массивами, будет сложнее вывести.
PDO::FETCH_GROUP группирует, но не выводит саму категорию
Я сделал, получилась такая штука
PHP:
$host = ‘localhost’; $db = ‘test’; $user = ‘root’; $pass = »; $charset = ‘utf8’; $dsn = «mysql:host=$host; dbname=$db;charset=$charset«; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $pdo = new PDO($dsn, $user, $pass, $opt); $sql = «SELECT category.name, category.id as catId, sub_category.name, sub_category.id FROM category LEFT JOIN sub_category ON sub_category.category_id = category.id»; $res = $pdo->query($sql)->fetchAll(PDO::FETCH_GROUP); echo ‘<ul>’; foreach($res as $key => $val) { echo ‘<li>’; echo ‘<a href=»/cat=».$val[0][«catId’].‘»>’.$key. ‘</a>’; echo ‘<ul>’; foreach($val as $k => $v) { echo ‘<li><a href=»sub-‘.$v[‘id’].‘»>’ . $v[‘name’] . ‘</a></li>’; } echo ‘</ul>’; echo ‘</li>’; } echo ‘</ul>’;
Я усложнил задачу, теперь надо у подкатегории вывести подкатегорию.
Убил 2 дня, перепробовал всякие способы, в итоге сделал свой велосипед на костылях, рекурсией мне такое задание сделать очень сложно.Такой код допускается на проекте? Какой способ ещё есть?
Делаю запрос
Код (Text):
SELECT category.id AS catId, category.name AS catName, sub_category.id AS subCatId, sub_category.name AS subCatName, page.id AS pageId, page.name AS pageName FROM category LEFT JOIN sub_category ON sub_category.category_id = category.id LEFT JOIN page ON page.sub_category_id = sub_category.id ORDER BY category.idМне присылается вот такой массив
PHP:
$res = [ [‘catId’ => 1, ‘catName’ => ‘Программы’, ‘subCatId’ => 1, ‘subCatName’ => «Антивирусы», ‘pageId’ => «1», ‘pageName’ => «Касперский»], [‘catId’ => 1, ‘catName’ => ‘Программы’, ‘subCatId’ => 4, ‘subCatName’ => «Аудио», ‘pageId’ => «4», ‘pageName’ => «VirtualDJ»], [‘catId’ => 1, ‘catName’ => ‘Программы’, ‘subCatId’ => 4, ‘subCatName’ => «Аудио», ‘pageId’ => «5», ‘pageName’ => «FL Studio»], [‘catId’ => 1, ‘catName’ => ‘Программы’, ‘subCatId’ => 1, ‘subCatName’ => «Антивирусы», ‘pageId’ => «6», ‘pageName’ => «NOD32»], [‘catId’ => 1, ‘catName’ => ‘Программы’, ‘subCatId’ => 2, ‘subCatName’ => «Запись», ‘pageId’ => «NULL», ‘pageName’ => «NULL»], [‘catId’ => 1, ‘catName’ => ‘Программы’, ‘subCatId’ => 3, ‘subCatName’ => «Интернет», ‘pageId’ => «NULL», ‘pageName’ => «NULL»], [‘catId’ => 2, ‘catName’ => ‘Фильмы’, ‘subCatId’ => 5, ‘subCatName’ => «Боевики», ‘pageId’ => «2», ‘pageName’ => «Джпеки Чан»], [‘catId’ => 2, ‘catName’ => ‘Фильмы’, ‘subCatId’ => 7, ‘subCatName’ => «Ужастики», ‘pageId’ => «3», ‘pageName’ => «Псы войны»], [‘catId’ => 2, ‘catName’ => ‘Фильмы’, ‘subCatId’ => 5, ‘subCatName’ => «Боевики», ‘pageId’ => «8», ‘pageName’ => «Американский ниндзя»], [‘catId’ => 2, ‘catName’ => ‘Фильмы’, ‘subCatId’ => 6, ‘subCatName’ => «Фантастика», ‘pageId’ => «NULL», ‘pageName’ => «NULL»], ];Потом я из него делаю другой массив, который мне нужен.
Вот так я его делаюPHP:
$mass = []; foreach($res as $cat) { $mass[$cat[‘catName’] . ‘|’ . $cat[‘catId’]] = [$cat[‘subCatName’] . ‘|’ . $cat[‘subCatId’]=> [$cat[‘pageId’]=>$cat[‘pageName’]]]; } else { $mass[$cat[‘catName’]. ‘|’ .$cat[‘catId’]][$cat[‘subCatName’] . ‘|’ .$cat[‘subCatId’]][$cat[‘pageId’]]=$cat[‘pageName’]; } }После этого получился вот такой массив
Код (Text):
Array ( [Программы|1] => Array ( [Антивирусы|1] => Array ( [1] => Касперский [6] => NOD32 ) [Аудио|4] => Array ( [4] => VirtualDJ [5] => FL Studio ) [Запись|2] => Array ( [] => ) [Интернет|3] => Array ( [] => ) ) [Фильмы|2] => Array ( [Боевики|5] => Array ( [2] => Джеки Чан [8] => Американский ниндзя ) [Ужастики|7] => Array ( [3] => Псы войны ) [Фантастика|6] => Array ( [] => ) ) )И потом уже, создаю списки
PHP:
echo ‘<ul>’; foreach($mass as $key => $val) { echo ‘<li><a href=»/category/’.$category[1].‘»>’.$category[0].‘</a>’; foreach($val as $k => $v) { echo ‘<ul>’; echo ‘<li><a href=»/sub-category/’.$subCategory[1].‘»>’.$subCategory[0].‘</a>’; foreach($v as $postKey => $postVal) { echo ‘<ul>’; echo ‘<li><a href=»/post/’.$postKey.‘»>’.$postVal.‘</a></li>’; echo ‘</ul>’; } echo ‘</li>’; echo ‘</ul>’; } echo ‘</li>’; } echo ‘</ul>’;Получается вот такое
Как-то странно у тебя данные хранятся. Зачем писать в каждой строке имя категории и имя подкатегории, если у них уже есть id? А если ты в последствии захочешь поменять название категории, ты будешь все строки в таблице менять?
На мой взгляд правильнее список категорий и подкатегорий хранить в отдельной таблице или массиве. Например так:PHP:
$category = [ 1 => [ ‘name’ => ‘Программы’, ‘subcategory’ => [ 1 => ‘Антивирусы’, 2 => ‘Запись’, 3 => ‘Аудио’, ] ], 2 => [ ‘name’ => ‘Фильмы’, ‘subcategory’ => [ 1 => ‘Боевики’, 2 => ‘Ужастики’, 3 => ‘Фантастика’, ] ], ];
@Sergey_Tsarev Не получается сделать такой массив
А почему в твоём массиве, у подкатегорий одинаковые ключи? Как потом запрос составлять?
@Dimon2x, используй нормальные инструменты хранения деревьев в базе: Nested Sets, Materialized Paths и пр.
@mkramer эта статья подойдёт? http://www.getinfo.ru/article610.html
@Dimon2x, вполне. + существует куча готовых библиотек для работы с Nested Sets
@mkramer применять сразу готовые решения, это наверно плохо, потому что так ничему не научусь
— Добавлено —
@mkramer эта библиотека нормальная? http://www.sesmikcms.ru/pages/read/…derevjami-nested-sets/?lang=ru&name=site_view
Ну, а в чем проблема? Примерно такой запрос:
Код (Text):
«SELECT `category` WHERE `catid` = ‘1’ AND `subcatid` = ‘2’»Или можно получить все записи и на php их уже отсортировать так как нужно.
— Добавлено —
А одинаковые ключи в подкатегориях потому, что они никак между собой не пересекаются. Ведь они находятся в массиве конкретной категории. Например, если мне нужно вызвать название категории с id равным 1 я напишу так:PHP:
echo $category[1][‘name’];А если хочу вызвать название подкатегории с id равным 2 из категории с id равным 1, то вот так:
PHP:
echo $category[1][‘subcategory’][2];
Ну ты по статье разберись, почему оно работает, а код из проекта проект таскать. Ну можно свою библиотеку замутить, в принципе
Наверное, не знаю. Я не пользовался. По описанию ничего
@Sergey_Tsarev в БД у подкатегории Аудио id 4, а у тебя в массиве 3, ну и как потом сделать запрос, что вывелись все под категории а Аудио?
— Добавлено —что-то я ни одной найти не могу
Ну я же тебе для примера написал
Напиши массив, чтобы как у тебя все было. А ещё лучше создай в базе данных отдельную таблицу для категорий и подкатегорий.
@Sergey_Tsarev так у меня и есть 3 таблицы для этого
@Dimon2x, ну так и сделай тогда три простых запроса к базе:
1. Получить список всех категорий:
Код (Text):
«SELECT * FROM ‘category'»2. Получить список всех подкатегорий:
Код (Text):
«SELECT * FROM ‘subcategory'»3.Список программ, фильмов и т.п.
Код (Text):
«SELECT * FROM ‘items'»А дальше выводи на экран.
@Sergey_Tsarev создавать несколько запросов, когда можно только 1 это плохо
Зачем, если есть решения, как неограниченную глубину подкатегорий хранить в одной таблице?
Да я и не спорю
Я это писал к тому, что вот так, на мой взгляд, лучше не делать:
PHP:
$mass[$cat[‘catName’] . ‘|’ . $cat[‘catId’]] = [$cat[‘subCatName’] . ‘|’ . $cat[‘subCatId’]=> [$cat[‘pageId’]=>$cat[‘pageName’]]];— Добавлено —
Лучше 3 простых запроса, чем один супернавороченный.
— Добавлено —
Да и данные полученные из первых двух запросов можно хранить в кэше или в сессии наример.
Кстати — а не быстрее для данной задачи — вначале выгрузить весь список категорий (целиком) и потом уже сдлеать обход полученного массива без запросов к базе?