sql + php显示带有infinit子类别的类别

时间:2015-10-27 12:30:54

标签: php mysql

我有下表:

CREATE TABLE category(
    category_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    parent INT DEFAULT NULL
);

如何从表中构建选择SQL,以便在php中我可以获得完整的类别和子类别树?我还想检查项目是否包含子项,因为我想添加一个类属性。

示例:

  • 电子
    • Smarthphones
      • iPhone
        • iPhone 5s
        • iPhone 6
        • iPhone 6s
      • 三星
    • TV
  • 食品

子类别可以超过这个例子。

我可以在php中使用此功能来显示菜单:

function treeview($array, $id = 0)
{

  foreach ($array as $arr)
  {

     if($arr[parent]==$id) {

     echo $arr[category_id].' '.$arr[parent].' '.$arr[name].'<br />';
     treeview($array, $arr['category_id']);

     }
   }
}

3 个答案:

答案 0 :(得分:2)

你也可以使用递归方法:

function buildTree($parent = null) {
    $sql = "SELECT * FROM `category` WHERE `parent` " . (is_null($parent) ? 'IS NULL' : "= '" . mysql_real_escape_string($parent) . "'");
    $result = mysql_query($sql) or die(mysql_error());
    $data = array();
    while ($row = mysql_fetch_assoc($result)) {
        $row['children'] = buildTree($row['category_id']);
        $data[] = $row;
    }
    return $data
}
$categories = buildTree();

答案 1 :(得分:2)

使用Andrey Telesh演示的常用结构,您可以执行以下操作:

<?php
function executeSQLThenFetchAllRowsAsAssoc($sql)
{
    global $pdo;
    $stmt=$pdo->prepare($sql);
    $stmt->execute();
    return $stmt->fetchAll();
}
function buildTree($parent = null)
{
    if(empty($parent)){
    $sql = "SELECT * FROM `category` WHERE `parent` is null";
    }else{
    $sql = "SELECT * FROM `category` WHERE `parent`=$parent";
    }
    $rows=executeSQLThenFetchAllRowsAsAssoc($sql);
    $data = array();
    foreach($rows as $row) {
        $cat=buildTree($row['category_id']);
        $data[] = array('children'=>$cat,'id'=>$row['category_id'],'parent'=>$row['parent'],'name'=>$row['name']);
    }
    return $data;
}

function displayIt($cats,$depth=0)
{
    if($depth==0){echo '<ul>';}
    foreach($cats as $cat)
    {
    $hasChildren=count($cat['children'])>0;
    $class=$hasChildren?' class="menu-item-has-children"':'';
    echo '<li'.$class.' data-children="'.count($cat['children']).'">'.$cat['name'];
    if($hasChildren){echo '<ul>';displayIt($cat['children'],$depth+1);echo '</ul>';}
    echo '</li>';
    }
    if($depth==0){echo '</ul>';}
}


$pdo=new PDO('mysql:host=localhost; dbname=my_database_name;', 'my_username', 'my_password');
$tree=buildTree();
displayIt($tree);

不需要关闭?>。只需确保使用您自己的设置替换最后的my_database_namemy_usernamemy_password。 是的,此代码将自行运行 输出将是:

<ul><li class="menu-item-has-children" data-children="2">Electronics<ul><li class="menu-item-has-children" data-children="2">Smarthphones<ul><li class="menu-item-has-children" data-children="3">iPhone<ul><li data-children="0">iPhone 5s</li><li data-children="0">iPhone 6</li><li data-children="0">iPhone 6s</li></ul></li><li data-children="0">Samsung</li></ul></li><li data-children="0">TV</li></ul></li><li data-children="0">Food</li></ul>

我测试的数据是:

CREATE TABLE IF NOT EXISTS `category` (
  `category_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `parent` int(11) DEFAULT NULL,
  PRIMARY KEY (`category_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;


INSERT INTO `category` (`category_id`, `name`, `parent`) VALUES
(1, 'Electronics', NULL),
(2, 'Smarthphones', 1),
(3, 'iPhone', 2),
(4, 'Food', NULL),
(5, 'Samsung', 2),
(6, 'iPhone 5s', 3),
(7, 'iPhone 6', 3),
(8, 'iPhone 6s', 3),
(9, 'TV', 1);

对于速度问题,在您使用buildTree()确定树层次结构后,我建议将类别缓存为序列化的php对象。您可能还有兴趣直接缓存您想要的HTML输出,或者同时执行这两项操作。每当更新类别表时,只需更新缓存即可。通过缓存,我的意思是有一个单独的PHP文件,您可以将其包含在项目中,这样您就可以在不打扰数据库的情况下获得数据。

答案 2 :(得分:1)

我在此方法中使用引用(&#34;&amp;&#34;):

function _getTree($tree_details){

$refs = array();
$list = array();

foreach ($tree_details as $data) {
$thisref = &$refs[ $data['branch_id'] ];

$thisref['branch_name'] = $data['branch_name'];
$thisref['parent_id'] = $data['parent_id'];
$thisref['branch_id'] = $data['branch_id'];

if ( empty($data['parent_id']) ){
$list[ $data['branch_id'] ] = &$thisref;
} else {
$refs[ $data['parent_id'] ]['children'][ $data['branch_id'] ] = &$thisref;
}

}

//check reviews tree
if( !empty($list) && count($list) ){
return $list;
}
return false;

} // getTree

此方法将返回所有类别的关联数组,然后您必须使用另一个使用递归函数绘制html的方法:

function drawBranchesSelectBox($branches_tree=NULL, $branch_id = 0, $options_string = '', $separator = '') {

if(empty($branches_tree)){
return false;
}

//loop through children
foreach ($branches_tree as $branches) {

$is_selected = ( $branch_id == $branches["branch_id"] ? ' selected="selected" ' : '' );
$options_string .= '' . $separator . $branches["branch_name"] . '' . "\n";

//check for subbranches
if (@is_array($branches['children']) && @count($branches['children'])) {
//call same method to get children
$options_string = drawBranchesSelectBox($branches['children'], $branch_id, $options_string, $separator . '    ');
}

} //foreach

return $options_string;

} //drawBranchesSelectBox