一个无限分类的处理类

  1   
  2/* 名称: 对分类操作的业务逻辑封装   
  3*   
  4* 作者: 帅的像人渣 QQ: 1191391 E-mail: [email protected]   
  5*   
  6* 完成日期: 2003-12-18 13:33   
  7*   
  8* 说明: 本类中引用的其它类(DB、Table、Item)均未提供,所以本类只能做个参考,不能直接应用   
  9* 不是本人小气不提供其它类,实在是因为那些都是一两年前写的类,很烂。怕大家看后对大   
 10* 造成误导. 在此发表这个类,只希望大家能从中学到一些程序设计的方法。   
 11* 授人以鱼不如授人以渔~   
 12*   
 13* 特点:   
 14* 采用递归调用的方法,对分类数据只需一次数据库查询可生成树状结构。 无限递归层次(视机器堆栈而定)   
 15*   
 16* 数据库定义:   
 17* ID smallint unsigned primary #如果数据量很大可用int   
 18* ParentID smallint unsigned index #如果数据量很大可用int, 请索引此字段   
 19* #如果为根分类,则ParentID = 0   
 20*   
 21* RootID smallint unsigned index #如果数据量很大可用int, 请索引此字段   
 22* #如果是根分类则RootID = 0, 否则RootID = 最上层的父分类ID   
 23* CategoryName varchar(n) #此大小自定   
 24* 如需有其它字段定义附在后面   
 25  
 26* 注意事项:   
 27* 不要试图直接调用本类,除非你有和我定义那另外那几个类相对应的接口, 否则不会成功   
 28* 在合适的地方定义 DBTABLE_CATEGORY 这个常量,使其指向你的分类数据表名字   
 29*   
 30* 程序构架:   
 31* ├─基础类
 32<!-- 完成底层数据库操作、数据抽象、语言、模板、异常、杂项等)操作 -->
 33* │   
 34* │   
 35* └─业务逻辑层(此类所处层次)
 36<!-- 利用基础类中数据操作、数据抽象等类根据表现层传递的参数完成数据处理,并返回数据或操作结果 -->
 37* │   
 38* │   
 39* └───表现层(用户界面)
 40<!-- 利用业务逻辑层将取得的数据或操作数据的结果通过基础类中的界面等类进行显示 -->
 41*/   
 42  
 43define('DBTABLE_CATEGORY', 'xxx');   
 44  
 45class Category_Logic   
 46{   
 47var $KernelRef = NULL; //系统核心的引用   
 48var $tblObj = NULL; //包含当前分类数据 Table 类的实例   
 49  
 50var $_CurrentItem = NULL; //包含当前分类数据 TItem类的实例   
 51  
 52var $CategoryID = 0; //当前分类ID,如果没有当前分类此项为 0   
 53  
 54//---------------------------------------------------------------------------   
 55//private array GetNodeData(array $Data, int $ParentNode)   
 56// 根据一颗指定根的并且以兄弟双亲法表示的树和当前分类的ID,返回当前分类在整个分类表中所处的位置   
 57//   
 58// @param: $Data 2维数组 Array(   
 59// Array(   
 60// 'ID' => 分类ID,   
 61// 'ParentID' => 父分类ID,   
 62// 'RootID' => 根分类ID,   
 63// 'CategoryName' => 分类名称,   
 64// ),   
 65// ……   
 66// );   
 67// 表示的一颗树   
 68//   
 69// @param: $ParentNode 父分类ID, 每一次由调用者给出,递归时由程序计算传递   
 70//   
 71// return value: 返回以兄弟双亲法表示的所有分类的树   
 72// 注意: 确保当前分类已经设置,否则此函数无返回   
 73//   
 74//---------------------------------------------------------------------------   
 75function GetNodeData( $Data, $ParentNode)   
 76{   
 77$arr = Array();   
 78  
 79$ArrayCount = 0;   
 80  
 81for( $i = 0, $cnt = Count( $Data); $i < $cnt; $i++)   
 82{   
 83if( $Data[ $i]['ParentID'] == $ParentNode)   
 84{   
 85$arr[ $ArrayCount] = $Data[ $i];   
 86$arr[ $ArrayCount++]['Child'] = $this->GetNodeData( $Data, $Data[ $i]['ID']);   
 87}   
 88}   
 89  
 90return $arr;   
 91}   
 92  
 93//---------------------------------------------------------------------------   
 94//private String _CurrentLevel(array $Data, int $Current, String $ProcessFunc = '')   
 95// 根据一颗指定根的并且以兄弟双亲法表示的树和当前分类的ID,返回当前分类在整个分类表中所处的位置   
 96//   
 97// @param: $Data 兄弟双亲法表示的树, 由调用者传递   
 98//   
 99// @param: $Current 当前分类ID,第一次调用时由调用者给出,递归时由程序自行计算   
100//   
101// @param: $ProcessFunc 指定对分类数据的处理函数, 函数原型定义见 $this->PrintCurrentLevel 中的注释   
102//   
103// return value: 返回当前分类在分类树中的位置   
104// 注意: 确保当前分类已经设置,否则此函数无返回   
105//   
106//---------------------------------------------------------------------------   
107function _CurrentLevel( $Data, $Current, $ProcessFunc = '')   
108{   
109for( $i = 0; $i < Count( $Data); $i++)   
110{   
111if( $Data[ $i]['ID'] == $Current)   
112{   
113if( $Data[ $i]['ParentID'] != 0)   
114{   
115$str = $this->_CurrentLevel( $Data, $Data[ $i]['ParentID'], $ProcessFunc) . ' -> ';   
116  
117if( $ProcessFunc) $str .= $ProcessFunc( $Data[ $i]);   
118else $str .= $Data[ $i]['CategoryName'];   
119}   
120else   
121{   
122if( $ProcessFunc) $str = $ProcessFunc( $Data[ $i]);   
123else $str = $Data[ $i]['CategoryName'];   
124}   
125break;   
126}   
127}   
128  
129return $str;   
130}   
131  
132//---------------------------------------------------------------------------   
133//public Category_Logic(Object & $Kernel, int $CategoryID = -1)   
134// 本类构造函数   
135//   
136// @param: $Kernel 此参数为当前系统核心类的一个引用, 核心类中包括   
137// 数据库类、输入输出类、系统配置类等   
138//   
139// @param: $CategoryID 当前分类ID。   
140// 当想调用 PrintCurrentLevel、GetRootID、GetParentID、GenerateTypeTreeList及   
141// 调用_CurrentItem成员的方法时请先设置此值.   
142//   
143// 调用GenerateTypeTreeList时设置此值,则没有ID为此的分类默认被选择,没设置则无默认   
144//   
145// return value: none   
146//   
147//---------------------------------------------------------------------------   
148function &Category_Logic(& $Kernel, $CategoryID = -1)   
149{   
150$this->KernelRef = & $Kernel;   
151  
152$this->tblObj = new Table( $Kernel->DBObj, DBTABLE_CATEGORY);   
153  
154if( $CategoryID != -1)   
155{   
156$this->SetCategoryID( $CategoryID);   
157}   
158}   
159  
160//---------------------------------------------------------------------------   
161//public void SetCategoryID(int $CategoryID)   
162// 设置当前分类ID   
163//   
164// return value: none   
165//   
166//---------------------------------------------------------------------------   
167function SetCategoryID( $CategoryID)   
168{   
169if(! $CategoryID) return;   
170  
171$Item = new TItem( $this->KernelRef->DBObj, DBTABLE_CATEGORY, '*', $CategoryID ,'ID');   
172  
173$this->_SelfData = & $Item;   
174  
175$this->CategoryID = $CategoryID;   
176}   
177  
178//---------------------------------------------------------------------------   
179//public int GetRootID()   
180// 返回当前分类的根分类ID   
181// 注意:只有设置的当前分类时此函数才有效   
182//   
183// return value: 返回当前分类的根分类ID   
184//   
185//---------------------------------------------------------------------------   
186function GetRootID()   
187{   
188return $this->_SelfData->Get('RootID');   
189}   
190  
191//---------------------------------------------------------------------------   
192//public int GetParentID()   
193// 返回当前分类的父分类ID   
194// 注意:只有设置的当前分类时此函数才有效   
195//   
196// return value: 返回当前分类的父分类ID   
197//   
198//---------------------------------------------------------------------------   
199function GetParentID()   
200{   
201if( $this->CategoryID) return $this->_SelfData->Get('ParentID');   
202}   
203  
204  
205//---------------------------------------------------------------------------   
206//public String GenerateTypeTreeList(array $Data, String $ProcessFunc, int $floor = 0)   
207// 返回整个分类的树状结构放在OptionList中的列表   
208//   
209// @param: $Data 此参数由 $this->DumpTypeDataToTree() 返回   
210//   
211// @param: $ProcessFunc 处理显示分类信息的回调函数, 函数原型请参照: $this->PrintCurrentLevel()   
212//   
213// @param: $floor 本参数不能人为给出,是程序自动计算的中间值   
214//   
215// return value:   
216// 结构为一颗兄弟双亲表示法表示的树   
217// 设如分类数据如下:   
218// ├──1级分类   
219// │   
220// │   
221// │   
222// ├─2级分类   
223// │ │   
224// │ └─3级分类   
225// │   
226// └─2级分类   
227//   
228// 则返回值为 Array(   
229// 0 => Array(   
230// 'ID' => '',   
231// 'ParentID' => '',   
232// 'RootID' => '',   
233// 'CategoryName' => '',   
234// 'Child' => ....   
235// )   
236// .....   
237// )   
238//   
239//---------------------------------------------------------------------------   
240function DumpTypeDataToTree( $RootID = 0, $Fields = '*')   
241{   
242$this->tblObj->SetFields( $Fields);   
243$this->tblObj->SetCondition('');   
244  
245$List = $this->tblObj->MapResult( $this->tblObj->Select());   
246  
247return $this->GetNodeData( $List, $RootID);   
248}   
249  
250//---------------------------------------------------------------------------   
251//public String GenerateTypeTreeList(array $Data, String $ProcessFunc = '', int $floor = 0)   
252// 返回整个分类的树状结构放在OptionList中的列表   
253//   
254// @param: $Data 此参数由 $this->DumpTypeDataToTree() 返回   
255//   
256// @param: $ProcessFunc 处理显示分类信息的回调函数, 函数原型请参照: $this->PrintCurrentLevel()   
257//   
258// @param: $floor 本参数不能人为给出,是程序自动计算的中间值   
259//   
260// return value: 返回一个

<option>分类名称1</option>

1...

<option>分类名称n</option>

1//   
2// ps: 调用时echo "

<select name="xxxx">" . $_c-&gt;GenerateTypeTreeList( $Data, 'ProcessFunc') . "</select>

 1";   
 2//   
 3//---------------------------------------------------------------------------   
 4function GenerateTypeTreeList( $Data, $ProcessFunc, $floor = 0)   
 5{   
 6$Str = '';   
 7for( $i = 0, $cnt = Count( $Data); $i < $cnt; $i++)   
 8{   
 9if( $this->CategoryID == $Data[ $i]['ID'])   
10{   
11$Str .= "

<option id']}'="" selected="" value="{ $Data[ $i][">"
. str_repeat(" ", $floor * 3)
. '├'
. ( $ProcessFunc ? $ProcessFunc( $Data[ $i]) : $Data[ $i]['CategoryName'])
. "</option>

1\n";   
2}   
3else   
4{   
5$Str .= "

<option id']}'="" value="{ $Data[ $i][">"
. str_repeat(" ", $floor * 3)
. '├'
. ( $ProcessFunc ? $ProcessFunc( $Data[ $i]) : $Data[ $i]['CategoryName'])
. "</option>

 1\n";   
 2}   
 3  
 4if( $Data[ $i]['Child']) $Str .= $this->GenerateTypeTreeList( $Data[ $i]['Child'], $ProcessFunc, $floor + 1);   
 5}   
 6  
 7return $Str;   
 8}   
 9  
10//---------------------------------------------------------------------------   
11//public String GenerateTypeTreeView(array $Data, String $ProcessFunc = '')   
12// 返回整个分类的树状结构视图   
13//   
14// @param: $Data 此参数由 $this->DumpTypeDataToTree() 返回   
15//   
16// @param: $ProcessFunc 处理显示分类信息的回调函数, 函数原型请参照: $this->PrintCurrentLevel()   
17//   
18// return value: 返回生成的一颗HTML形式显示的树   
19//   
20//---------------------------------------------------------------------------   
21function GenerateTypeTreeView( $Data, $ProcessFunc)   
22{   
23$Str = '

<ul style="Line-Height:200%">';

for( $i = 0, $cnt = Count( $Data); $i &lt; $cnt; $i++)
{
if( $ProcessFunc) $Str .= '<li>' . $ProcessFunc( $Data[ $i]) . '</li>' . "\n";
else $Str .= '<li>' . $Data[ $i]['CategoryName'] . '</li>' . "\n";

if( $Data[ $i]['Child']) $Str .= '<li>' . $this-&gt;GenerateTypeTreeView( $Data[ $i]['Child'], $ProcessFunc) . '</li>';
}

$Str .= '</ul>

  1';   
  2  
  3return $Str;   
  4}   
  5  
  6//---------------------------------------------------------------------------   
  7//public String PrintCurrentLevel(String $ProcessFunc = '')   
  8// 对多级分类生成当前位置字符串   
  9// 设如分类数据如下,当前分类为3级分类, 则调用返回 1级分类 -> 2级分类 -> 3级分类   
 10// ├──1级分类   
 11// │   
 12// │   
 13// │   
 14// ├─2级分类   
 15// │ │   
 16// │ └─3级分类   
 17// │   
 18// └─2级分类   
 19//   
 20//   
 21//   
 22//   
 23// @param: $ProcessFunc 此为对分类数据如何显示的回调函数,不设置则直接显示分类名称   
 24// 函数定义原型为 function (& $arr);   
 25// 其中 $arr参数为每一个分类信息的一维数组如下:   
 26// array(ID => 1, ParentID => 0, RootID => 0, CategoryName => '1级分类')   
 27// 返回值为对上述数据处理的结果,比如返回带链接的分类名字、更改显示颜色等   
 28//   
 29// return value: 返回当前分类在整个分类树中所处位置   
 30//   
 31//---------------------------------------------------------------------------   
 32function PrintCurrentLevel( $ProcessFunc = '')   
 33{   
 34if(! $this->CategoryID) return '';   
 35  
 36if( $this->_SelfData->Get("RootID") == 0)   
 37{   
 38if( $ProcessFunc) return $ProcessFunc( $this->_SelfData->fetchDataToArray());   
 39else return $this->_SelfData->Get("CategoryName");   
 40}   
 41  
 42$Current = $this->CategoryID;   
 43  
 44$this->tblObj->SetCondition('RootID = ' . $this->_SelfData->Get('RootID') . " or ID = " . $this->_SelfData->Get('RootID'));   
 45  
 46$Data = $this->tblObj->MapResult( $this->tblObj->Select());   
 47  
 48return $this->_CurrentLevel( $Data, $Current, $ProcessFunc);   
 49}   
 50  
 51//---------------------------------------------------------------------------   
 52//public boolean Add(array $arr)   
 53// 添加新分类到分类表中   
 54//   
 55// @param: $arr 在此数组中包括对新添加分类的定义, 定义如下:   
 56//   
 57// $arr['RootID'] 新分类所属的根分类ID   
 58// $arr['ParentID'] 新分类的父分类ID   
 59// $arr['CategoryName'] 新分类的名称   
 60//   
 61// return value: 返回添加分类操作结果   
 62//   
 63//---------------------------------------------------------------------------   
 64function Add( $arr)   
 65{   
 66$this->tblObj->SetFields(   
 67Array(   
 68'RootID',   
 69'ParentID',   
 70'CategoryName',   
 71)   
 72);   
 73  
 74return $this->tblObj->Insert(   
 75Array(   
 76$arr['RootID'],   
 77$arr['ParentID'],   
 78$arr['CategoryName'],   
 79)   
 80);   
 81}   
 82  
 83//---------------------------------------------------------------------------   
 84//public boolean Delete(int $ID)   
 85// 删除已经存在的分类   
 86//   
 87// @param: $ID 要删除的分类ID   
 88//   
 89// return value: 返回删除分类操作结果   
 90//   
 91//---------------------------------------------------------------------------   
 92function Delete( $ID)   
 93{   
 94$sysOption = & $this->KernelRef->Config;   
 95  
 96$this->tblObj->SetFields('*');   
 97$this->tblObj->SetCondition('ID = ' . (int) $ID);   
 98  
 99return $this->tblObj->Delete();   
100}   
101  
102//---------------------------------------------------------------------------   
103//public boolean Modify(int $ID, array $arr)   
104// 修改已经存在的分类   
105//   
106// @param: $ID 要修改的分类ID   
107// @param: $arr 在此数组中包括修改后的分类定义, 定义如下:   
108//   
109// $arr['RootID'] 新分类所属的根分类ID   
110// $arr['ParentID'] 新分类的父分类ID   
111// $arr['CategoryName'] 新分类的名称   
112//   
113// return value: 返回修改分类操作结果   
114//   
115//---------------------------------------------------------------------------   
116function Modify( $ID, $arr)   
117{   
118$this->tblObj->SetCondition('ID = ' . (int) $ID);   
119  
120$prev = $this->tblObj->MapOneRow( $this->tblObj->Select());   
121  
122$this->tblObj->SetFields(   
123Array(   
124'RootID',   
125'ParentID',   
126'CategoryName',   
127)   
128);   
129  
130return $this->tblObj->Update( $arr);   
131}   
132  
133//---------------------------------------------------------------------------   
134//public array Modify(int $ID)   
135// 修改已经存在的分类   
136//   
137// @param: $ID 指定的分类ID   
138//   
139// return value: 返回指定ID分类的信息   
140// 数组中包括:   
141// Array(   
142// 'ID' => 分类ID,   
143// 'ParentID' => 父分类ID,   
144// 'RootID' => 根分类ID,   
145// 'CategoryName' => 分类名称,   
146// );   
147//   
148//---------------------------------------------------------------------------   
149function GetCategory( $ID)   
150{   
151$this->tblObj->SetCondition('ID = ' . (int) $ID);   
152  
153return $this->tblObj->MapOneRow( $this->tblObj->Select());   
154}   
155}   
Published At
Categories with Web编程
Tagged with
comments powered by Disqus