php 进阶_php 进阶:实现无限分类

php 进阶:实现无限分类

更新时间:2006年12月16日 00:00:00   作者:

1.分析

我们在用 php 制作网站时,分类是很重要的,在分类下面又再分类这第二个分类称为次分类,而现在大多数网站分类只分到第三类:

第一分类(父分类)-->第二分类(子分类)-->第三分类(孙分类)

这种亲缘分类越多,程序和数据库的控制就越加的复杂困难.在同一级的分类处理和控制是非常的简单的,因为只需要一个数据库来记载这一级的分类就行了,如:系统,新闻等分类,在这一级上处理是很简单的,但对一个网站来说一级分类是不够的,还需要再分类,如:

系统-->linux,windows

新闻-->linux 新闻,windows 新闻

这样分类就清晰些了,至少让人明白了,系统包括 linux 和 windows,而新闻包括 linux 新闻和 windows 新闻,为了让信息资料更加清晰,于是再继续分类:

linux-->系统工具,内核,编程语言,开发工具

...

分类到了第三级,信息资料的处理就更清晰了,也就是说为了很清晰地处理资料,分类越详细就越方便,这样即方便处理信息又方便网友目的明确地查找到需要的资料,但随着不断的细化分类,在程序和数据库的控制上就会越来越困难.

困难一:如何在数据库里处理这些互有关联的亲缘分类?

困难二:如何用 php 完成这种一目了然的关系?

这种分级多而细的分类是每个 php 程序员都必须解决的问题,因为制作一个好而出色的网站分类问题是不可避免的,而解决这个问题又是相当复杂的,其中最大的问题就是数据库的分类处理,因为如果数据库处理不当将会带来巨大的工作量甚至是不得不重新规划数据库...

这并不是夸张,因为很多人在数据库处理上就会采用一级分类建立一个数据库的做法,我当时也是采取这种方法处理分类的,因大多网站都是分到第三级,所以数据库里只需三个分类数据库来进行处理.但是需要继续向下分类时,这种做法的弊端就显露出来了,因为越往下分,工作量,程序量将会巨增..

我要介绍的这种方法就是如何用一个分类数据库建立无限向下分级的分类方法,用过 windows 的读者都知道 windows 文件夹就可以建立无限分级的目录,可在目录下面继续建立目录,这样没完没了的分下去,Linux 的目录创建也有这种功能,我介绍的这个方法跟这种形式相同.

2.数据库的规划

------------------------------------------------------------

前面谈到分类的复杂性,因此如何规划数据库便成为了实现无限分类非常重要的一步.

我曾介绍过论坛的数据库规划,不错论坛能够实现无限的跟接,无限分类便是这种形式的扩展,分类同样是这种子父的关联关系,所以分类的数据库就是如何确立明确这种子父关系,这里面有几个难点.

1)如何处理各分类的信息存储;

2)如何处理分类的亲缘关系;

3)如何处理对信息的查询;

亲缘关系的数据库处理与论坛的数据库处理类似,这里建个 type 的数据库用来处理分类:

建立字段:

id(int):用来记录各分类的自然序号

uid(int):用来记录该分类的父分类的 id 号

type(char):类别的名称

roue_id(varchar):亲缘树,以 :0:2:10:20: 的 id 连接表明亲源关系

roue_char(varchar):亲缘树,类似 :系统:linux:开发工具:gcc: (这个字段有没有都没关系,为了更方便地了解各亲缘关系当然字符表述比数字表述更直接^o^,不过最好加上这个字段)

这样一个无限分类的类别表就建立了起来,接下来就需要建立存储信息的数据库,处理查询一个表最方便所以这里建立一个表存储信息 type_message:

id(int):信息的序号;

typeid(int):所属类别的 id 号;

title(varchar):信息标题;

message(text):信息内容;

time:信息建立的时间;

这两个数据表就能够完成无限分类的这个任务了(两个表的辅助字段就没加了,读者可自行加入).

剩下的任务就全部交由 php 来处理完成.

3.程序控制

------------------------------------------------------------

实现无限分类这个功能中就属这一步最为复杂辛苦,首先看看程序需要完成的步骤:

1)创建分类上传;

2)创建信息上传;

3)明确显示各分类及其之间的关系;

4)处理查询功能;

5)如何处理编辑和删除的功能;

而这五步中最为困难的就是第五个步骤,因为对分类的编辑和删除涉及到一至性的问题.

下面我就逐一描述 php 的程序控制:

1)创建分类上传

在介绍这个功能前,先介绍一下 explode( ) 这个函数,这是个字串处理函数,用来分解字串的,具体的用法,例:

分解"0:1:2:3:4"里的数字

$val='0:1:2:3:4';

$rid=explode(":",$val);

经过 explode( ) 函数处理,$val 内的所有数字都分解到 $rid 数组中了,要引用时只需打印:echo '$rid[0],$rid[1],$rid[2]..."; 就行了.explode( ) 函数在整个分类处理中起着非常重要的作用,好现在开始介绍无现分类的程序控制.

可以假设个总分类 0 ,所有的分类都是它的子孙分类,现在来建立第一个分类'系统',来看看它在数据库的存储形式:

id | uid | type | rout_id | rout_char

1 | 0 | 系统 | 0:1 | 系统

接着又在下面分'Linux':

id | uid | type | rout_id | rout_char

2 | 1 | Linux| 0:1:2 | 系统:Linux

以上就是数据库存储的形式,现在就来完成 php 的代码,这与论坛的代码很相似,我们所要做的就是将分类的 id 放入 uid,而父分类的 uid 就放 0,下面来看看代码:

.....

.....

//设置默认页

if (empty($func)) $func=='showtype';

//设置父分类的 uid

if (empty($uid)) $uid=0;

//数据库存储************************************************

if ($func=='save'):

$fields = "";

$values = "";

if ($id!="") {

$fields .= ",id";

$values.=",$id";

}

if ($uid!="") {

$fields .= ",uid";

$values.=",$uid";

}

if ($type!="") {

$fields .= ",type";

$values.=",'$type'";

}

if ($route_id=="") {

//取得父分类的 route_id

if ($uid!=0) {

$result = mysqlquery("select * from type where id=$uid");

$route_id=mysql_result($result,0,"route_id");

} else {

$routr_id='0';

}

$fields .= ",route_id";

//形成自己的 route_id

$route_id="$route_id:$id";

$values.=",'$route_id'";

}

//形成自己的 route_char

if ($route_char!="") {

$fields .= ",route_char";

$route_char="$route_char:$type";

$values.=",'$route_char'";

} else {

$fields .= ",route_char";

$route_char=$type;

$values.=",'$route_char'";

}

$fields = substr($fields,1,strlen($fields)-1);

$values = substr($values,1,strlen($values)-1);

$result = mysqlquery("insert into type ($fields) values ($values)");

...

endif; /* end save */

//分类上传************************************************

if ($func=='createtype'):

//取得自己的 id

$result = mysqlquery("select * from type order by

id desc");

$num=mysql_numrows($result);

if (!empty($num)) {

$cat = mysql_result($result,0,"id");

} else {

$cat=0;

}

//判断分类的状态

if ($uid != 0) {

$result=mysql_query("select * from type where id=$uid");

$type=mysql_result($result,0,"type");

$route_char=mysql_result($result,0,"route_char");

} else {

$type='父分类';

}

echo "

";

echo "

echo "

所属类别:$type";

echo "

创建分类:";

echo "

";

$cat=$cat+1;

echo "";

echo "";

echo "";

echo "

";

echo "

";

echo "

";

endif; /* end createtype */

//显示分类************************************************

if ($func=='showtype'):

echo "

//判断分类的状态

if ($uid!=0) {

$result=mysql_query("select * from type where id=$uid");

$type=mysql_result($result,0,"type");

} else {

$type='父分类';

}

echo "

创建分类";

echo "

$type";

$result=mysql_query("select * from type where uid=$uid");

$num=mysql_numrows($result);

if (!empty($num)) {

for ($i=0;$i

$id=mysql_result($result,$i,"id");

$type=mysql_result($result,$i,"type");

echo "

";

echo "$type";

echo "

";

}

}

echo "

";

endif; /* end showtype */

.....

.....

?>

以上的程序便完成了无限分类的基本创建,存储和显示,接着就是完善分类创建功能的各个部分了.

4.路径跟踪

------------------------------------------------------------

前面已经介绍过了分类的创建实现方法,在分类表里记载了 rout_id 和 rout_char 这两个存储分类路径的信息,在不做任何处理的情况下,程序只能够顺序下到最底层的分类而无法倒退(当然可利用浏览器的 back 键倒退,但这对程序来说是不完整的),因此必须将 rout_id 和 rout_char 的信息分解出来完成实在的路径指示.

具体的做法,假如数据库记载了这么一条分类信息:

id:4

uid:2

type:开发工具

rout_id:0:1:2:4

rout_char:系统:linux:开发工具

当程序走到分类'开发工具'上时,除了要求显示路径信息外还要求能够去到路径上的任一分类中,该怎么做能?这里就需要用到 explode() 函数了.因为 rout_id 和 rout_char 是对应关系的,所以可将它们分解:

$path=explode(":",$rout_id);

$path_gb=explode(":",$rout_char);

这时所有分类信息都被分解了,现在要做的就是以链接的方式还原路径信息:

for ($i=0;;$i++) {

$a=$i+1;

echo "

href=$php_self?func=showtype&uid=",$path[$a],">",$path_gb[$i],"

:";

if (empty($path_gb[$i])) {

break;

}

}

上面这段代码就实现了加链接还原路径的功能,因为实现的是无限分类,因此是没有上限的,所以在 for($i=0;;$i++) 里没有范围限制,而设置循环退出的条件是 $path_gb[$i] 中的值为空,将这段代码插入类别显示版面的程序块内就行了:

.....

.....

//显示分类************************************************

if ($func=='showtype'):

echo "

//判断分类的状态

if ($uid!=0) {

$result=mysql_query("select * from type where id=$uid");

$type=mysql_result($result,0,"type");

//******** 新加入的代码 ***************

$rout_id=mysql_result($result,0,"rout_id");

$rout_char=mysql_result($result,0,"rout_char");

$path=explode(":",$rout_id);

$path_gb=explode(":",$rout_char);

echo "

";

for ($i=0;;$i++) {

$a=$i+1;

echo "

href=$php_self?func=showtype&uid=",$path[$a],">",$path_gb[$i],"

:";

if (empty($path_gb[$i])) {

break;

}

}

echo "

";

//******** end ***********************

} else {

$type='父分类';

}

echo "

创建分类";

echo "

$type";

$result=mysql_query("select * from type where uid=$uid");

$num=mysql_numrows($result);

if (!empty($num)) {

for ($i=0;$i

$id=mysql_result($result,$i,"id");

$type=mysql_result($result,$i,"type");

echo "

";

echo "$type";

echo "

";

}

}

echo "

";

endif; /* end showtype */

.....

.....

?>

完成这个功能块后,就可继续分类信息的显示实现了...

相关文章

1a1b05c64693fbf380aa1344a7812747.png

这篇文章主要介绍了php常用字符串比较函数,实例汇总了substr_compare、strncasecmp、strncmp、strcoll等常用函数,具有一定的参考借鉴价值,需要的朋友可以参考下2014-11-11

4f55910a645b073bc4fc65dc10dc14bd.png

这篇文章主要介绍了PHP会话控制,结合实例形式分析了php针对cookie与session的相关操作技巧,需要的朋友可以参考下2016-12-12

0ea3c7666119d5615e582f823fb3fad6.png

本篇文章是对spl_autoload_register与autoload的区别进行了详细的分析介绍,需要的朋友参考下2013-06-06

4f96a78db829b1556ff16de21e013c7a.png

PHP 中由于数组和字符串这两种变量类型是如此常用,以至于 PHP 具有两个函数,可以在字符串和数组之间互相进行转换2013-03-03

8cc1031babc6aff2319f1c6af8544aa0.png

php小偷相关截取函数备忘,需要的朋友可以参考下。2010-11-11

0c932a99bb7b6f23c937db507070cc7b.png

本篇文章是对php调用MsSQL存储过程使用内置RETVAL获取过程中的return值的方法进行了详细的分析介绍,需要的朋友参考下2013-07-07

cca732bf65a93ed2ec0ac80c638460fe.png

本文讲的是php无限级评论嵌套实例介绍, 我在设计BB的过程中,也一直在思考是否可以不通过递归来实现无限级分类的结构展现和父子结构查找,因为如果不对这里的算法进行优化后果可能是致命的2018-04-04

2d9f31f2af7b675a3d153d2b7f1035a7.png

这篇文章主要介绍了PHP中static关键字以及与self关键字的区别,本文讲解了static关键字的定义、迟绑定(Late Static Bindings)、以及与self关键字的区别等内容,需要的朋友可以参考下2016-05-05

b452cee8ec5cd9e58ab98eba17281e59.png

大家在开发过程中,经常会考虑到一些php的代码的执行效率问题,这样我们的程序才会运行的更加流畅,这里简单的总结小,需要的朋友可以参考下。2010-07-07

f4838ec7e2d4da28e0b57d4e852dadd4.png

这篇文章主要介绍了PHP获取链表中倒数第K个节点的方法,涉及php针对链表的遍历、判断等相关操作技巧,需要的朋友可以参考下2018-01-01

最新评论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值