显示嵌套的类别,子类别和文章

时间:2014-08-11 05:09:00

标签: php sql pdo

我有两张桌子:

1。文章:
id, title, content, catid

2。类:
id, title, parent

现在我想在一个框中显示所有类别。这些框应包含所有子类别(= parent)作为框和所有文章(= catid)

e.g。

Box Vegetables (Level 1)
    Box Red vegetables (Level 2)
        Tomatoes
        Beetroot
    Box Green vegetables (Level 2)
        Cucumber
    Other vegetable 1 (article)
    Other vegetable 2 (article)
Box Cars (Level 1)
    BoxRacing Cars (Level 2)
        F1 Racing Car
        Nascar Car
    Ford Fiesta (article)
    Opel Corsa (article)

这是我的SQL和PHP尝试。

$categories = $db->prepare('SELECT id, title FROM categories');
$subcategories = $db->prepare('SELECT id, title FROM categories WHERE parent = :id');
$articles = $db->prepare('SELECT id, title, content FROM articles WHERE catid = :id');

$categories->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
$categories->execute();
if ($categories->rowCount()) {
    while($cat = $categories->fetch(PDO::FETCH_OBJ)) {
        echo '<div class="list">';
        echo cat->title;
            $subcategories->bindParam(':id', $cat->id, PDO::PARAM_INT);
            $subcategories->execute();
            if ($subcategories->rowCount()) {
                while($subcat = $subcategories->fetch(PDO::FETCH_OBJ)) {
                    echo '<div class="list">';
                    echo subcat->title;

                    $art->bindParam(':id', $subcat->id, PDO::PARAM_INT);
                    $art->execute();
                    if ($art->rowCount()) {
                        while($article = $art->fetch(PDO::FETCH_OBJ)) {
                            echo $article->title;
                        }
                    }

                    echo '</div>';
                }
            }

            $art->bindParam(':id', $cat->id, PDO::PARAM_INT);
            $art->execute();
            if ($art->rowCount()) {
                while($article = $art->fetch(PDO::FETCH_OBJ)) {
                    echo $article->title;
                }
            }

        echo '</div>';
    }
}

我能更有效率吗?我真的需要那么多SQL语句和while循环吗?

2 个答案:

答案 0 :(得分:0)

代码未经测试,请参阅注释:

//You're fetching everything anyway, so why not do it in a single step?
$categories = $db->prepare('SELECT id, title, parent FROM categories');
$articles = $db->prepare('SELECT id, title, content, catid FROM articles');

$categories->execute();
$articles->execute();

//Now we've got a mess, let's organize it
$categoriesById = array();
$childrenCategories = array();
$articlesByCategory = array();

while($cat = $categories->fetch(PDO::FETCH_OBJ)) {
    $categoriesById[$cat->id] = $cat;
    if ($cat->parent) $childrenCategories[$cat->parent] = $cat;
}
while($article = $articles->fetch(PDO::FETCH_OBJ)) {
    $articlesByCategory[$article->catid][] = $article;
}

//A function for printing the categories, so that we can call it recursively
function printCategory($category, $childrenCategories, $articlesByCategory) {
   echo '<div class="list">';
   echo $category->title;

    foreach($childrenCategories as $childrenCategory) {
        printCategory($childrenCategory, array(), $articlesByCategory);
    }

    if (!empty($articlesByCategory[$category->id])) {
        $article = $articlesByCategory[$category->id];
        echo $article->title;
    } 

   echo '</div>';
}

//Print out stuff
foreach($categoriesById as $id => $category) {
    if ($category->parent) continue; //Skip subcategories
    printCategory(
        $category,
        !empty($childrenCategories[$id]) ? $childrenCategories[$id] : array(),
        $articlesByCategory
    );
}

答案 1 :(得分:0)

我的观点是在数据库中形成数据。

首先,我认为没有articles的{​​{1}}不能在描述的系统中。得出这样的结论后,我创建了一个查询来获取具有条件的数据,并实现了两个附加条件:

  1. 某些父类别没有子类别。
  2. 有些文章有父类别,但没有子类别。
  3. 这是一个怪异的查询,用于在一个地方捕获所有描述的数据:

    category

    您可以在这里找到example of using this query

    使用此查询在数据库中保存VIEW并将其用作PHP中的表。 例如,让我们将此查询命名为VIEW select article_id, article_title, article_content, article_catid, catid, subcatid, category, subcategory from (select articles.id as article_id, articles.title as article_title, articles.content as article_content, articles.catid as article_catid, cats_n_subs.catid, null as subcatid, cats_n_subs.category, null as subcategory from (select categories.id as catid,subcategories.id as subcatid, categories.title as category, subcategories.title as subcategory from (select * from categories where parent is null) as categories left join (select id, title, parent from categories where parent is not null union all select null, null, null) as subcategories on subcategories.parent = categories.id or subcategories.id is null group by categories.id, subcategories.id, categories.title, subcategories.title ) as cats_n_subs left join articles on articles.catid = cats_n_subs.catid group by articles.id, articles.title, articles.content, articles.catid, cats_n_subs.catid,cats_n_subs.category union all select articles.id as article_id, articles.title as article_title, articles.content as article_content, articles.catid as article_catid, cats_n_subs.catid, cats_n_subs.subcatid as subcatid, cats_n_subs.category, cats_n_subs.subcategory as subcategory from (select categories.id as catid,subcategories.id as subcatid, categories.title as category, subcategories.title as subcategory from (select * from categories where parent is null) as categories left join categories as subcategories on subcategories.parent = categories.id ) as cats_n_subs left join articles on articles.catid = cats_n_subs.subcatid where articles.id is not null) as cats_n_arts order by category, case when subcategory is null then 1 else 0 end, subcategory;

    下一步是在PHP中准备和使用数据:

    cats_n_arts

    不幸的是,我没有可能测试这段代码,但它应该可以正常工作。