Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
sql+php显示具有无限子类别的类别_Php_Mysql - Fatal编程技术网

sql+php显示具有无限子类别的类别

sql+php显示具有无限子类别的类别,php,mysql,Php,Mysql,我有下表: CREATE TABLE category( category_id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20) NOT NULL, parent INT DEFAULT NULL ); 如何从表中构建selectsql,以便在php中获得类别和子类别的完整树?我还想检查一个项是否有子项,因为我想添加一个class属性 例如: 电子学 智能手机 苹果手机 iphone5s iphone6 iphone6s

我有下表:

CREATE TABLE category(
    category_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    parent INT DEFAULT NULL
);
如何从表中构建selectsql,以便在php中获得类别和子类别的完整树?我还想检查一个项是否有子项,因为我想添加一个class属性

例如:

电子学 智能手机 苹果手机 iphone5s iphone6 iphone6s 三星 电视 食物 子类别可以比这个例子更多

我可以在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']);

     }
   }
}

在这种方法中,我使用引用(&R):

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 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();

使用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);
我测试的数据是:

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输出感兴趣,或者两者兼而有之。每当更新categories表时,只需更新缓存即可。所谓缓存,我的意思是在项目中包含一个单独的PHP文件,这样可以在不影响数据库的情况下获得数据。

使用我的代码,我想知道如何检查当前项是否有子项。请阅读问题。使用我的代码,我想知道如何检查当前项目是否有子项。请阅读问题。您的答案很好,但使用问题中我更新的代码,如何确定当前项目是否有子项?您可能会说要进行选择,但我希望此函数像助手一样在多个位置使用它。我在codeigniter中实现。这应该是我的完整代码:如您所见,我需要当前的\u项\u have \u child。如果元素有子元素,我已经更新了我的答案以包含该类。还请注意,我只需编辑displayIt即可获得结果。从buildTree返回的结构仍然保持不变,当您对视图进行这样的更改时,它可能已被缓存。谢谢,效果很好。我接受了他的回答。您是否也可以提供没有echo的版本并返回$html?我试图用$html来实现这一点,但没有成功。只需使用输出缓冲:ob_start;和ob_get_clean,或定义一个公共字符串变量,并在每次递归时将输出附加到公共字符串变量。然后当循环完成引用公共变量时,我使用第三个参数来显示它,$html,并用$html替换echo.=以避免在函数之外定义其他变量。但是没有成功。
<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);