Система категорий и подкатегорий/дети бесконечные


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

Изучал простую структуру и адаптирована базу данных и скрипт регистрации правильно, но моя самая большая проблема в настоящее время в часть представления.

Используя в качестве основы следующие записи: IMAGEM

, Перечисляя способом, который адаптировал (учитывая, неправильной) у меня есть некоторые ограничения, потому что, когда дело доходит до детей, подразделов, уже детей не указываются, мне нужен простой скрипт, который делает такая процедура и что именно для легкой настройки.

в Настоящее время у меня есть следующий результат:
Resultado

Мой сценарий для текущего списка:

<?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 "&nbsp;&nbsp;&nbsp;&nbsp;".$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 "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".$rowSubFilho->cat_nome."<br/>";
        endwhile;

    endwhile;

} //fecha while categoria raiz

echo "</ul>"; ?>

Примечание.- Я знаю, что есть и другие способы, размечать категории, кроме " " однако, в данном случае-это только для тестирования.
Сценарий, в котором привел выше использует FETCH_ASSOC вместо FETCH_OBJ

Author: Tiago Boeing, 2014-04-13

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("&nbsp;", $nivel * 4);
        // Nome da categoria
        $html .= $row->cat_nome . '<br>';
        // Filhos
        $html .= desceNaArvore($row->cat_id, $nivel + 1);
    endwhile;
    return $html;
}

echo desceNaArvore();
?>

Возможных точек совершенствования

  • Используйте вложенные списки вместо отступов по пространство.

  • Отделите логику получения данных от логики представления. Идеальным, с точки зрения организации кода, будет иметь рекурсивную функцию, чтобы получить данные (в виде массивов вложенных), и другой, также рекурсивно, чтобы преобразовать данные массива в HTML. Как совет упражнений, если вы хотите изучить подробнее о теме :)

 7
Author: bfavaretto, 2014-04-15 19:29:04

И В базе данных, такой результат, что вы ищете-это тип запроса, который больше известен как 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

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

 7
Author: Erico, 2014-04-14 01:49:11

Благодарю @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 отличный по быть простой и легкой адаптации. Спасибо!

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

 0
Author: Tiago Boeing, 2014-04-15 19:53:59