【问题标题】:Display nested categories, subcategories and articles显示嵌套类别、子类别和文章
【发布时间】:2014-10-03 20:42:06
【问题描述】:

我有两张桌子:

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

2。类别:
id, title, parent

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

例如

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 循环吗?

【问题讨论】:

    标签: php sql pdo


    【解决方案1】:

    代码未经测试,请参阅 cmets:

    //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
        );
    }
    

    【讨论】:

      【解决方案2】:

      我的意思是在数据库内部形成数据。

      首先,我认为没有categoryarticles 不能在所描述的系统中。在得出这样的结论后,我创建了一个查询来根据您的条件获取数据,它实现了两个附加条件:

      1. 某些父类别没有子类别。
      2. 有些文章有父类别,但没有子类别。

      这是一个可怕的查询,用于在一个地方捕获所有描述的数据:

      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;
      

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

      将此查询保存在数据库中,并将其用作 PHP 中的表。 例如,让我们将此查询命名为 VIEW 为cats_n_arts

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

      <?php
        $cats_n_arts = $db->prepare('SELECT article_id, article_title, article_content, article_catid, catid, subcatid, category, subcategory FROM cats_n_arts');
        $cats_n_arts->execute();
        $parent = 0;
        $subcat = -1;
        // use one WHILE cycle and several IF's to run through all the data rows:
        while($row = $cats_n_arts->fetch(PDO::FETCH_OBJ)) {
          if ($row->catid != $parent) {
            if ($parent > 0) { 
              if ($subcat > -1){
                echo ' </div>';       
                $subcat = -1;
              }
              echo '</div>';
            }
           echo '<div class="list">';
           echo $row->category;
           $parent = $row->catid;
          }
          if ($row->subcatid) {
            if ($subcat > -1){
             echo ' </div>';
            }
            if ($subcat != $row->subcatid) {
              echo ' <div class="list">';
              echo $row->subcategory;
              $subcat = $row->subcatid;
            }
          } else {
            if ($subcat > 0){
              echo ' </div>';
            }
            if ($subcat != 0){
              echo ' <div class="list">';
              echo ' OTHER ';
              $subcat = 0;
            }
          }
          if ($row->article_id) {
            echo $row->article_title;
          }
        }
      ?>
      

      很遗憾,我无法测试此代码,但它应该可以正常工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-27
        • 2018-09-10
        • 1970-01-01
        • 2012-10-14
        • 1970-01-01
        • 2014-04-07
        • 2021-12-22
        • 1970-01-01
        相关资源
        最近更新 更多