Система категорий и подкатегорий/дети бесконечные
Я верхом система категорий и подкатегорий, бесконечные, просто начала. Нашел скрипт в интернете, который удовлетворяет требованиям, однако его настройки и адаптации, чтобы мой проект стал почти непригодным для использования.
Изучал простую структуру и адаптирована базу данных и скрипт регистрации правильно, но моя самая большая проблема в настоящее время в часть представления.
Используя в качестве основы следующие записи:
, Перечисляя способом, который адаптировал (учитывая, неправильной) у меня есть некоторые ограничения, потому что, когда дело доходит до детей, подразделов, уже детей не указываются, мне нужен простой скрипт, который делает такая процедура и что именно для легкой настройки.
в Настоящее время у меня есть следующий результат:
Мой сценарий для текущего списка:
<?php
echo "<ul>";
$selCategorias2 = $conn->prepare("SELECT * FROM cat WHERE cat_pai = ?");
$selCategorias2->execute(array(0));
while($rowCategoria2 = $selCategorias2->fetch(PDO::FETCH_OBJ)){
echo $rowCategoria2->cat_nome."<BR/>";
$selFilhos = $conn->prepare("SELECT * FROM cat WHERE cat_pai = ?");
$selFilhos->execute(array($rowCategoria2->cat_id));
while($rowFilho = $selFilhos->fetch(PDO::FETCH_OBJ)):
echo " ".$rowFilho->cat_nome."<br/>";
$selSubFilhos = $conn->prepare("SELECT * FROM cat WHERE cat_pai = ?");
$selSubFilhos->execute(array($rowFilho->cat_id));
while($rowSubFilho = $selSubFilhos->fetch(PDO::FETCH_OBJ)):
echo " ".$rowSubFilho->cat_nome."<br/>";
endwhile;
endwhile;
} //fecha while categoria raiz
echo "</ul>"; ?>
Примечание.- Я знаю, что есть и другие способы, размечать категории, кроме " " однако, в данном случае-это только для тестирования.
Сценарий, в котором привел выше использует FETCH_ASSOC вместо FETCH_OBJ
3 answers
Такую структуру базы данных, вы можете использовать рекурсивную функцию (функция, которая вызывает себя) в PHP, чтобы извлечь из дерева, так много уровней, что есть в базе. Недостатком этого является то, что требуются несколько запросов к базе данных.
Учитывая ваш текущий код, и самый короткий путь будет в функцию следующим образом:
<?php
function desceNaArvore($cat_pai = 0, $nivel = 0) {
global $conn;
$html = "";
$query = $conn->prepare("SELECT * FROM cat WHERE cat_pai = ?");
$query->execute(array($cat_pai));
while($row = $query->fetch(PDO::FETCH_OBJ)):
// Padding com espaços de acordo com o nível da categoria
$html .= str_repeat(" ", $nivel * 4);
// Nome da categoria
$html .= $row->cat_nome . '<br>';
// Filhos
$html .= desceNaArvore($row->cat_id, $nivel + 1);
endwhile;
return $html;
}
echo desceNaArvore();
?>
Возможных точек совершенствования
Используйте вложенные списки вместо отступов по пространство.
Отделите логику получения данных от логики представления. Идеальным, с точки зрения организации кода, будет иметь рекурсивную функцию, чтобы получить данные (в виде массивов вложенных), и другой, также рекурсивно, чтобы преобразовать данные массива в HTML. Как совет упражнений, если вы хотите изучить подробнее о теме :)
И В базе данных, такой результат, что вы ищете-это тип запроса, который больше известен как Hierarchical query (Query иерархической или query, рекурсивные) список смежности.
Существует довольно много дискуссий об этом, потому что MySQL - не поддерживает queries иерархических, как и другие Субд имеют как PostgreSQL и Oracle. Вы найдете несколько решений, юродивый ai создавая обширные stored procedures, не очень эффективный.
Самый простой способ извлечения данных с помощью списка смежности и с определенном количество уровней, с помощью LEFT JOIN, был бы более простым и более быстрым, что, создавая петли внутри петли в PHP, выполнив несколько запросов, но даже так, эта модель является далеко не идеальной, потому что он имеет некоторые ограничения основные.
Будет выглядеть следующим образом:
SELECT t1.cat_nome AS lev1, t2.cat_nome as lev2, t3.nome as lev3, t4.cat_nome as lev4
FROM cat AS t1
LEFT JOIN cat AS t2 ON t2.cat_pai = t1.cat_id
LEFT JOIN cat AS t3 ON t3.cat_pai = t2.cat_id
LEFT JOIN cat AS t4 ON t4.cat_pai = t3.cat_id
Решение: Nested Model
, Если вы можете изменить структуру вашей базы данных, я рекомендую вам использовать эту модель, в mysql это самый простой способ (читать можно) получить данные так, рекурсивно.
Там в статье довольно подробно, что говорит достаточно о модели, структура и реализует его.
Решение 2: Closure table
И другое решение, также возможно, что создает дополнительные таблицы для хранения иерархии записей.
Благодарю @bfavaretto за ответ, что также очень помогло и заставило меня replanejar конструкция более простая, но я хочу поделиться здесь также, как я была решена ранее получить ответы.
В моем случае я просто адаптируя немного для отображения данных, вы можете настроить, как вы хотите, в этом случае просто измените функцию.
function imprimeMenuInfinito( array $menuTotal , $idPai = 0, $nivel = 0 )
{
// abrimos a ul do menu principal
echo str_repeat( "\t" , $nivel ),'<ul>',PHP_EOL;
// itera o array de acordo com o idPai passado como parâmetro na função
foreach( $menuTotal[$idPai] as $idMenu => $menuItem)
{
// imprime o item do menu
echo str_repeat( "\t" , $nivel + 1 ),'<li>',"ID: ", $menuItem['id']," - ", $menuItem['name'], ' <a href=?id=', $menuItem['id'], '>Excluir</a> <a href=?id_cat=', $menuItem['id'],'>Adicionar subcategoria</a> <a href=?edita_cat=', $menuItem['id'], '>Editar</a>' , PHP_EOL;
// se o menu desta interação tiver submenus, chama novamente a função
if( isset( $menuTotal[$idMenu] ) ) imprimeMenuInfinito( $menuTotal , $idMenu , $nivel + 2);
// fecha o li do item do menu
echo str_repeat( "\t" , $nivel + 1 ),'</li>',PHP_EOL;
}
// fecha o ul do menu principal
echo str_repeat( "\t" , $nivel ),'</ul>',PHP_EOL;
}
Здесь мы показываем функции:
$query = $conn->query('SELECT * FROM cat ORDER BY cat_nome ASC');
while($row = $query->fetch(PDO::FETCH_OBJ)){
$menuItens[$row->cat_pai][$row->cat_id] = array('name' => $row->cat_nome, 'pai' => $row->cat_pai, 'id' => $row->cat_id);
}
echo imprimeMenuInfinito($menuItens);
Я Считаю, что ответ @bfavaretto отличный по быть простой и легкой адаптации. Спасибо!
Не забыть файл подключения
При добавлении новых атрибутов пожаловать в банке, вы должны отправить их через массив для функции, а затем вызвать их в функции.