`
xuebingnanmm
  • 浏览: 175241 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

PHP无限分类的原理

    博客分类:
  • PHP
阅读更多
以下是无限分类的分析原理,总结出来的是效率比较慢,功能实现了,如果有更好的方法 请评论下。

 ·什么是无限分类呢?就像windows下新建一个文件夹,在新建的文件夹下又可以新建一个文件夹,这样无限循环下去,无限分类也是这样,父类可以分出它子类,子类又可以分出它的子类,这样一直无限循环下去。

 

·那PHP又是如何实现它的无限分类的呢?如何把它的各个分类一一列出来呢?首先我们假设有这样的一个三级分类,新闻→PHP新闻→PHP6.0出来了。如果我们要查找“PHP6.0出来了”这条新闻,我们先点击新闻,然后再点击PHP新闻就可以查出来了,也就是说我们可以通过祖父类一级一级地往下找,反过来我们只要知道一个子类的父类,就可以把它查找出来了。这样我们在设计数据库时就可以多设计一个父类id的字段就可以实现无限分类的功能了。

 

//我们建一个表"class"
CREATE TABLE `class` (
  `id` int(11) NOT NULL auto_increment COMMENT '分类id',
  `f_id` int(11) NOT NULL COMMENT '父id',
  `name` varchar(25) collate gbk_bin NOT NULL COMMENT '分类名称',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=gbk COLLATE=gbk_bin AUTO_INCREMENT=1 ;
 
//首先我们往数据库里插入‘新闻’这个大分类,因为‘新闻’是最大分类,上面没有父类了,所以我把它的f_id设置为0。
INSERT INTO `class` (`id`, `f_id`, `name`) VALUES(1, 0, '新闻');   //id这个字段是自动增长的,可以不写值。
 
//然后我们再往数据库里插入‘PHP新闻’这个分类,它的父类‘新闻’的id是1,所以它的f_id设置为1。
INSERT INTO `class` (`id`, `f_id`, `name`) VALUES(2, 1, 'PHP新闻');
 
//然后我们再往数据库里插入‘PHP6.0出来了’这个分类,它的父类‘PHP新闻’的id是2,所以它的f_id设置为2。
INSERT INTO `class` (`id`, `f_id`, `name`) VALUES(3, 2, 'PHP6.0出来了');
 
//同理,我们可以这样一直往下插入分类,也就达到了无限分类。
//我们可以发现插入一个分类的原则关键是找到这个分类的父类的id,然后作为这个分类的f_id字段的值。
//假设要插入跟‘新闻’同一个级别的分类‘技术’,也就是说它也是最大分类,上面没有父类了,那么它的f_id也设置为0;
INSERT INTO `class` (`id`, `f_id`, `name`) VALUES(4, 0, '技术'); 
 
//在‘技术’下面又有一个分类‘PHP技术’,那么我们怎么插入呢,首先找到‘PHP技术’的父类‘技术’的id,然后作为自己的f_id字段的值。
INSERT INTO `class` (`id`, `f_id`, `name`) VALUES(5, 4, 'PHP技术'); 
 
//看到这里,想必大家应该都明白怎么往数据库里插入各个分类了。就不再举例了。

 

我们已经知道如何往数据库里插入各个分类了,那又如何把各个分类罗列出来呢?

 

<?php
header("Content-type:text/html;charset=utf-8"); 
$db=new mysqli("localhost","root","","news_php100") ; //实例化一个数据库连接。使用这个前一定要确保已经加载了mysqli类库,或者用mysql_connect这个方式连接。 
if(mysqli_connect_errno()){
 	echo "链接失败:".mysqli_connect_error();
 	exit(); } 
$db->query("set names utf8");
$result=$db->query("select name from class where f_id=0"); //查找f_id=0的分类,也就是查找每一个大类。
while($row=$result->fetch_assoc()){
      echo $row['name']."<br>";        //这样就把每个大类循环出来了。
}
//同样我们可以把新闻的子类循环出来。
$result=$db->query("select * from class where f_id=1"); //查找f_id=1的分类,也就是查找‘新闻’的子类。
while($row=$result->fetch_assoc()){
      echo $row['name']."
";        //这样就把‘新闻’的子类循环出来了。注意:只是子类,不包括孙子类。
}
//写到这里,我们会发现一个问题,如果这个分类是10级分类,难道我们要写10个循环把它每个子类循环出来?如果是更多级分类呢,这样写显然是不现实的。
//那又有什么办法解决呢?我们可以写一个递归的函数,把f_id作为参数传入,不断循环每一个f_id的值,也就是说把每一个f_id值的子类循环出来。
//首先我们把各个分类的值保存在一个二维数组中,在下面的递归函数里有用。
$result=$db->query("select * from class");
while($row=$result->fetch_assoc()){
     $arr[]=array($row[id],$row[f_id],$row[name]);    //每一行保存一个分类的id,f_id,name的信息。
}

fenlei();

function fenlei($f_id=0){     //$f_id初始化为0,也就是从最大分类开始循环.
    global $arr;   //声明$arr为全局变量才可在函数里引用。
    for($i=0;$i<count($arr);$i++){       //对每个分类进行循环。
           if($arr[$i][1]==$f_id){         //$arr[$i][1]表示第$i+1个分类的f_id的值。开始$f_id=0,也就是把f_id=0的分类输出来。
                 echo $arr[$i][2]."<br>"; //$arr[$i][1]表示第$i+1个分类的name的值。
            fenlei($arr[$i][0]);   //$arr[$i][1]表示第$i+1个分类的id的值。进行递归,也就是把自己的id作为f_id参数把自己的子类再循环出来。
}
}
}
?>

 

真正调试:

--
-- 表的结构 `cms_admin_action`
--

CREATE TABLE IF NOT EXISTS `cms_admin_action` (
  `action_id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL,
  `action_code` text COLLATE utf8_unicode_ci NOT NULL,
  `action_title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `action` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
  `url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `sorder` int(3) NOT NULL,
  PRIMARY KEY (`action_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=15 ;

 

 

<?php   
header("Content-type:text/html;charset=utf-8");    

$db=new mysqli("127.0.0.1","root","root","cms") ; 
if(mysqli_connect_errno())
{   
	echo "链接失败:".mysqli_connect_error();   
	exit(); 
}    

$db->query("set names utf8");  

$result=$db->query("select * from cms_admin_action");  
while($row=$result->fetch_assoc())
{   
     $arr[]=array($row['action_id'],$row['parent_id'],$row['action_title']); 
}

fenlei();

function fenlei($f_id=0,$lever=1)
{
	global $arr;
	
	if($f_id == 0) 
		$lever=1;
	else
		$lever +=1;

	for($i=0;$i<count($arr);$i++)
	{
		if($arr[$i][1]==$f_id)
		{
			echo "No.".$lever." Lever:".$arr[$i][2]."<br>"; 
			fenlei($arr[$i][0],$lever);
		}   
	}   
}   
?>  

 

另外一种思路(效果比较高,逻辑处理稍复杂):http://www.w3pop.com/learn/view/p/4/o/0/doc/php_nolimit_class/

 

 

其他的无限分类代码:

 

/**
* author: askie
* blog: http://www.pkphp.com
* 版权: 随便用
* 无限分类
*/
class Tree
{
        public $data=array();
        public $cateArray=array();
        
        function Tree()
        {
               
        }
        function setNode ($id, $parent, $value)
    {
        $parent = $parent?$parent:0;
        $this->data[$id]                = $value;
        $this->cateArray[$id]        = $parent;
    }
    function getChildsTree($id=0)
    {
            $childs=array();
            foreach ($this->cateArray as $child=>$parent)
            {
                    if ($parent==$id)
                    {
                            $childs[$child]=$this->getChildsTree($child);
                    }
                    
            }
            return $childs;
    }
    function getChilds($id=0)
    {
            $childArray=array();
            $childs=$this->getChild($id);
            foreach ($childs as $child)
            {
                    $childArray[]=$child;
                    $childArray=array_merge($childArray,$this->getChilds($child));
            }
            return $childArray;
    }
    function getChild($id)
    {
            $childs=array();
            foreach ($this->cateArray as $child=>$parent)
            {
                    if ($parent==$id)
                    {
                            $childs[$child]=$child;
                    }
            }
            return $childs;
    }
    //单线获取父节点
    function getNodeLever($id)
    {
            $parents=array();
            if (key_exists($this->cateArray[$id],$this->cateArray))
            {
                    $parents[]=$this->cateArray[$id];
                    $parents=array_merge($parents,$this->getNodeLever($this->cateArray[$id]));
            }
            return $parents;
    }
    function getLayer($id,$preStr='|-')
    {
            return str_repeat($preStr,count($this->getNodeLever($id)));
    }
    function getValue ($id)
    {
        return $this->data[$id];
    } // end func
}

/*$Tree = new Tree("请选择分类");
//setNode(目录ID,上级ID,目录名字);
$Tree->setNode(1, 0, '目录1');
$Tree->setNode(2, 1, '目录2');
$Tree->setNode(5, 3, '目录5');
$Tree->setNode(3, 0, '目录3');
$Tree->setNode(4, 2, '目录4');
$Tree->setNode(9, 4, '目录9');
$Tree->setNode(6, 2, '目录6');
$Tree->setNode(7, 2, '目录7');
$Tree->setNode(8, 3, '目录8');

//print_r($Tree->getChildsTree(0));
//print_r($Tree->getChild(0));
//print_r($Tree->getLayer(2));

$category = $Tree->getChilds();

//遍历输出
foreach ($category as $key=>$id)
{
    echo $id.$Tree->getLayer($id, '|-').$Tree->getValue($id)."\n";
}*/

?>

 

分享到:
评论
1 楼 872890971 2011-08-18  
echo "No.".$lever." Lever:".$arr[$i][2]."<br>"; 
怎么用变量调用。

相关推荐

    PHP无限分类的原理.

    本文将详细解析PHP实现无限分类的原理,并通过递归的应用来阐述其实现过程。 首先,理解无限分类的核心在于表示层级关系。在数据库设计中,通常会为每个分类设置两个字段:`id`(主键)和`parent_id`(父分类ID)。...

    PHP无限级分类算法原理及实例演示

    那PHP又是如何实现它的无限分类的呢?如何把它的各个分类一一列出来呢? 首先我们假设有这样的一个三级分类,新闻→PHP新闻→PHP6.0出来了。 如果我们要查找“PHP6.0出来了”这条新闻,我们先点击新闻,然后再点击...

    php实现无限分类php实现无限分类

    1. **无限分类的原理** 无限分类通常基于树形结构,每个节点都有一个父节点(除了根节点),并且可以有任意数量的子节点。在数据库设计中,通常会用到自引用关联,即分类表中的一个字段(如`parent_id`)引用同一表...

    php无限分类例子,源码。

    以下是对这个PHP无限分类源码的详细解析。 1. **无限分类原理** 无限分类通常基于自引用关联或层级标识符(如“路径”或“深度”)来实现。在这个例子中,可能使用了后者,即通过在数据库中为每个分类添加一个表示...

    PHP无限分类[增强版].zip

    在压缩包中的`PHP无限分类[增强版].php`文件是类库的核心代码,通过分析和理解这个文件,开发者可以了解其实现原理,并根据自己的项目需求进行定制。`php中文网免费下载站.txt`和`php中文网下载站.url`可能是相关...

    无限分类带数据库

    首先,我们需要了解PHP中的无限分类实现原理。通常有两种主要方法:递归函数和层级序号(如左值右值或路径法)。递归函数是通过调用自身来处理子分类,而层级序号则通过为每个分类分配一个表示其位置的数字,以便...

    小贤php无限分类

    接下来,我们将详细讨论PHP无限分类的基本原理、实现方法以及可能涉及到的相关技术。 1. **无限分类的概念** 无限分类允许类别拥有无限级别的子类别,形成一个树状结构。在数据库中,通常通过自引用的方式实现,即...

    PHP无限分类之PHP

    总的来说,PHP无限分类是通过递归或预排序树形遍历等技术实现的,它在很多实际应用中都发挥着重要作用。通过理解这些概念和技术,开发者可以更好地管理和展示复杂的数据结构,提升网站或应用的用户友好性。在实际...

    初学者 php无限分类

    这个"初学者 php无限分类"的资源提供了一种简单的实现方法,适合那些正在学习PHP编程的新手。 无限分类的核心思想是利用递归或者自连接的方式来处理具有层级关系的数据。在这个源码中,可能包括了如何存储分类数据...

    PHP 的无限级分类

    在PHP编程中,无限级分类是一种常见的需求,特别是在处理如文章分类、商品...以上就是关于PHP无限级分类的基本原理、实现方法和应用场景的详细说明。通过理解这些知识,开发者能够有效地处理和展示具有层级关系的数据。

    php无限分类的示例

    首先,我们需要理解无限分类的基本原理。无限分类通常依赖于自引用外键或递归方式来实现。在这个例子中,我们采用数组实现,这在数据量不大或不需要实时动态添加分类的情况下非常实用。 1. **自引用外键**: 在...

    自己写的php 递归无限分类 附有sql文件

    本项目提供的资源包含了一个用PHP实现的无限分类系统,并附带了SQL文件,方便我们理解其工作原理。 首先,我们要讨论的是递归。递归是一种算法,它通过调用自身来解决问题。在无限分类中,递归常被用来遍历层级关系...

    php无限分类树类方法.zip

    这个类库下载("php无限分类树类方法")应该包含了这个`CategoryTree`类的完整实现,以及可能的测试用例和示例数据,帮助开发者快速理解和使用。在实际项目中,你可以根据具体需求对这个类进行扩展,例如增加缓存...

    简单易用的php无限分类树

    本篇文章将详细解析“简单易用的PHP无限分类树”的原理及其应用。 无限分类树,顾名思义,就是可以容纳无限层级的分类结构。在数据库设计中,它通常采用自引用的方式,即一个分类可以有多个子分类,子分类还可以有...

    PHP无限分类

    **PHP无限分类的实现原理** PHP无限分类通常基于两种方法:递归和非递归(比如栈或队列)。 1. **递归方法**: 这种方法通过函数自身调用来实现,每次调用都将当前分类的子分类添加到结果集中,直到没有子分类...

    PHP树结构,实现无限分级

    在本文中,我们将深入探讨如何使用PHP来实现无限级分类的树形结构,并通过实际的代码示例来展示其工作原理。 首先,我们需要理解树结构的基本概念。在树结构中,每个节点(Node)都有一个值和零个或多个子节点。根...

    php无限分类

    以下是对这个PHP无限分类程序的详细解读: 1. **无限分类的基本原理** 无限分类通常基于自引用关联或层级标识符(如“父ID”)来实现。每个分类可以有任意数量的子分类,形成树状结构。在这个程序中,可能使用了...

    php+ajax+无限级分类(下拉菜单形式)

    本示例“php+ajax+无限级分类(下拉菜单形式)”展示了如何利用PHP、AJAX和HTML来创建一个动态的、能够处理无限级分类的下拉菜单系统。下面我们将深入探讨这个系统的组成部分和实现原理。 首先,我们来看数据表的设计...

    php无限分类程序,包含了数据库直接运行使用

    这个“php无限分类程序”就是解决此类问题的一个工具。 首先,无限分类在数据库设计中通常采用自引用的方式实现。`tvmenu.sql`可能是包含了一个已经构建好的无限分类表结构的SQL文件。在该文件中,很可能有一个名为...

    Category类库:php无限分类类库

    Category类库是PHP编程中用于实现无限分类的一个实用工具,它极大地简化了处理层次结构数据的复杂性。在网站或应用程序中,无限分类通常用于管理如产品目录、文章分类、用户组等,其中子类别可以无限层级地嵌套。...

Global site tag (gtag.js) - Google Analytics