Php 显示嵌套的类别、子类别和项目

Php 显示嵌套的类别、子类别和项目,php,sql,pdo,Php,Sql,Pdo,我有两张桌子: 一,。第条: id、标题、内容、catid 二,。类别: id、标题、父项 现在我想在一个框中显示所有类别。框中应包含所有子类别=父类as框和所有项目=catid e、 g 这是我的SQL和PHP尝试 $categories = $db->prepare('SELECT id, title FROM categories'); $subcategories = $db->prepare('SELECT id, title FROM categories WHERE p

我有两张桌子:

一,。第条: id、标题、内容、catid

二,。类别: id、标题、父项

现在我想在一个框中显示所有类别。框中应包含所有子类别=父类as框和所有项目=catid

e、 g

这是我的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循环吗?

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

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

我的观点是在数据库内部形成数据

首先,我认为没有分类的文章是不可能在系统中被描述的。在得出这样的结论之后,我创建了一个查询来获取具有您的条件的数据,它实现了两个附加条件:

某些父类别没有子类别。 有些文章有父类别,但没有子类别。 下面是一个用于在一个位置捕获所有描述数据的异常查询:

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\u 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;
    }
  }
?>
不幸的是,我没有可能测试这段代码,但它应该可以正常工作

<?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;
    }
  }
?>