PHP代码:——————————————————————————–
<?php
/* 名称: 对分类操作的业务逻辑封装
* 说明: 本类中引用的其它类(DB、Table、Item)均未提供,所以本类只能做个参考,不能直接应用
* 不是本人小气不提供其它类,实在是因为那些都是一两年前写的类,很烂。怕大家看后对大
* 造成误导. 在此发表这个类,只希望大家能从中学到一些程序设计的方法。
* 特点:
* 采用递归调用的方法,对分类数据只需一次数据库查询可生成树状结构。 无限递归层次(视机器堆栈而定)
*
* 数据库定义:
* ID smallint unsigned primary #如果数据量很大可用int
* ParentID smallint unsigned index #如果数据量很大可用int, 请索引此字段
* #如果为根分类,则ParentID = 0
*
* RootID smallint unsigned index #如果数据量很大可用int, 请索引此字段
* #如果是根分类则RootID = 0, 否则RootID = 最上层的父分类ID
* CategoryName varchar(n) #此大小自定
* 如需有其它字段定义附在后面
* 注意事项:
* 不要试图直接调用本类,除非你有和我定义那另外那几个类相对应的接口, 否则不会成功
* 在合适的地方定义 DBTABLE_CATEGORY 这个常量 190-711 190-721 ,使其指向你的分类数据表名字
*
* 程序构架:
* ├─基础类 <!– 完成底层数据库操作、数据抽象、语言、模板、异常、杂项等)操作 –>
* │
* │
* └─业务逻辑层(此类所处层次) <!– 利用基础类中数据操作、数据抽象等类根据表现层传递的参数完成数据处理,并返回数据或操作结果 –>
* │
* │
* └───表现层(用户界面) <!– 利用业务逻辑层将取得的数据或操作数据的结果通过基础类中的界面等类进行显示 –>
*/
define(‘DBTABLE_CATEGORY’, ‘xxx’);
class Category_Logic
{
var KernelRef = NULL; //系统核心的引用
var tblObj = NULL; //包含当前分类数据 Table 类的实例
var _CurrentItem = NULL; //包含当前分类数据 TItem类的实例
var CategoryID = 0; //当前分类ID,如果没有当前分类此项为 0
//—————————————————————————
//private array GetNodeData(array Data, int ParentNode)
// 根据一颗指定根的并且以兄弟双亲法表示的树和当前分类的ID,返回当前分类在整个分类表中所处的位置
//
// @param: Data 2维数组 Array(
// Array(
// ‘ID’ => 分类ID,
// ‘ParentID’ => 父分类ID,
// ‘RootID’ => 根分类ID,
// ‘CategoryName’ => 分类名称,
// ),
// ……
// );
// 表示的一颗树
//
// @param: ParentNode 父分类ID, 每一次由调用者给出,递归时由程序计算传递
//
// return value: 返回以兄弟双亲法表示的所有分类的树
// 注意: 确保当前分类已经设置,否则此函数无返回
//
//—————————————————————————
function GetNodeData(Data, ParentNode)
{
arr = Array();
ArrayCount = 0;
for(i = 0, cnt = Count(Data); i < cnt; i++)
{
if(Data[i][\'ParentID\'] == ParentNode)
{
arr[ArrayCount] = Data[i];
arr[ArrayCount++][\'Child\'] = this->GetNodeData(Data, Data[i][\'ID\']);
}
}
return arr;
}
//—————————————————————————
//private String _CurrentLevel(array Data, int Current, String ProcessFunc = ”)
// 根据一颗指定根的并且以兄弟双亲法表示的树和当前分类的ID,返回当前分类在整个分类表中所处的位置
//
// @param: Data 兄弟双亲法表示的树, 由调用者传递
//
// @param: Current 当前分类ID,第一次调用时由调用者给出,递归时由程序自行计算
//
// @param: ProcessFunc 指定对分类数据的处理函数, 函数原型定义见 this->PrintCurrentLevel 中的注释
//
// return value: 返回当前分类在分类树中的位置
// 注意: 确保当前分类已经设置,否则此函数无返回
//
//—————————————————————————
function _CurrentLevel(Data, Current, ProcessFunc = ”)
{
for(i = 0; i < Count(Data); i++)
{
if(Data[i][\'ID\'] == Current)
{
if(Data[i][\'ParentID\'] != 0)
{
str = this->_CurrentLevel(Data, Data[i][\'ParentID\'], ProcessFunc) . ‘ -> ‘;
if(ProcessFunc) str .= ProcessFunc(Data[i]);
else str .= Data[i][\'CategoryName\'];
}
else
{
if(ProcessFunc) str = ProcessFunc(Data[i]);
else str = Data[i][\'CategoryName\'];
}
break;
}
}
return str;
}
//—————————————————————————
//public Category_Logic(Object &Kernel, int CategoryID = -1)
// 本类构造函数
//
// @param: Kernel 此参数为当前系统核心类的一个引用, 核心类中包括
// 数据库类、输入输出类、系统配置类等
//
// @param: CategoryID 当前分类ID。
// 当想调用 PrintCurrentLevel、GetRootID、GetParentID、GenerateTypeTreeList及
// 调用_CurrentItem成员的方法时请先设置此值.
//
// 调用GenerateTypeTreeList时设置此值,则没有ID为此的分类默认被选择,没设置则无默认
//
// return value: none
//
//—————————————————————————
function &Category_Logic(&Kernel, CategoryID = -1)
{
this->KernelRef = &Kernel;
this->tblObj = new Table(Kernel->DBObj, DBTABLE_CATEGORY);
if(CategoryID != -1)
{
this->SetCategoryID(CategoryID);
}
}
//—————————————————————————
//public void SetCategoryID(int CategoryID)
// 设置当前分类ID
//
// return value: none
//
//—————————————————————————
function SetCategoryID(CategoryID)
{
if(!CategoryID) return;
Item = new TItem(this->KernelRef->DBObj, DBTABLE_CATEGORY, ‘*’, CategoryID ,’ID’);
this->_SelfData = &Item;
this->CategoryID = CategoryID;
}
//—————————————————————————
//public int GetRootID()
// 返回当前分类的根分类ID
// 注意:只有设置的当前分类时此函数才有效
//
// return value: 返回当前分类的根分类ID
//
//—————————————————————————
function GetRootID()
{
return this->_SelfData->Get(‘RootID’);
}
//—————————————————————————
//public int GetParentID()
// 返回当前分类的父分类ID
// 注意:只有设置的当前分类时此函数才有效
//
// return value: 返回当前分类的父分类ID
//
//—————————————————————————
function GetParentID()
{
if(this->CategoryID) return this->_SelfData->Get(‘ParentID’);
}
//—————————————————————————
//public String GenerateTypeTreeList(array Data, String ProcessFunc, int floor = 0)
// 返回整个分类的树状结构放在OptionList中的列表
//
// @param: Data 此参数由 this->DumpTypeDataToTree() 返回
//
// @param: ProcessFunc 处理显示分类信息的回调函数, 函数原型请参照: this->PrintCurrentLevel()
//
// @param: floor 本参数不能人为给出,是程序自动计算的中间值
//
// return value:
// 结构为一颗兄弟双亲表示法表示的树
// 设如分类数据如下:
// ├──1级分类
// │
// │
// │
// ├─2级分类
// │ │
// │ └─3级分类
// │
// └─2级分类
//
// 则返回值为 Array(
// 0 => Array(
// ‘ID’ => ”,
// ‘ParentID’ => ”,
// ‘RootID’ => ”,
// ‘CategoryName’ => ”,
// ‘Child’ => ….
// )
// …..
// )
//
//—————————————————————————
function DumpTypeDataToTree(RootID = 0, Fields = ‘*’)
{
this->tblObj->SetFields(Fields);
this->tblObj->SetCondition(”);
List = this->tblObj->MapResult(this->tblObj->Select());
return this->GetNodeData(List, RootID);
}
//—————————————————————————
//public String GenerateTypeTreeList(array Data, String ProcessFunc = ”, int floor = 0)
// 返回整个分类的树状结构放在OptionList中的列表
//
// @param: Data 此参数由 this->DumpTypeDataToTree() 返回
//
// @param: ProcessFunc 处理显示分类信息的回调函数, 函数原型请参照: this->PrintCurrentLevel()
//
// @param: floor 本参数不能人为给出,是程序自动计算的中间值
//
// return value: 返回一个<option>分类名称1</option> … <option>分类名称n</option>
//
// ps: 调用时echo “<select name=’xxxx’>” . _c->GenerateTypeTreeList(Data, ‘ProcessFunc’) . “</select>”;
//
//—————————————————————————
function GenerateTypeTreeList(Data, ProcessFunc, floor = 0)
{
Str = ”;
for(i = 0, cnt = Count(Data); i < cnt; i++)
{
if(this->CategoryID == Data[i][\'ID\'])
{
Str .= “<option value=’{Data[i][\'ID\']}’ selected>”
. str_repeat(“ ”, floor * 3)
. ‘├’
. (ProcessFunc ? ProcessFunc(Data[i]) : Data[i][\'CategoryName\'])
. “</option>\\n”;
}
else
{
Str .= “<option value=’{Data[i][\'ID\']}’>”
. str_repeat(“ ”, floor * 3)
. ‘├’
. (ProcessFunc ? ProcessFunc(Data[i]) : Data[i][\'CategoryName\'])
. “</option>\\n”;
}
if(Data[i][\'Child\']) Str .= this->GenerateTypeTreeList(Data[i][\'Child\'], ProcessFunc, floor + 1);
}
return Str;
}
//—————————————————————————
//public String GenerateTypeTreeView(array Data, String ProcessFunc = ”)
// 返回整个分类的树状结构视图
//
// @param: Data 此参数由 this->DumpTypeDataToTree() 返回
//
// @param: ProcessFunc 处理显示分类信息的回调函数, 函数原型请参照: this->PrintCurrentLevel()
//
// return value: 返回生成的一颗HTML形式显示的树
//
//—————————————————————————
function GenerateTypeTreeView(Data, ProcessFunc)
{
Str = ‘<ul style=”Line-Height:200%”>’;
for(i = 0, cnt = Count(Data); i < 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->GenerateTypeTreeView(Data[i][\'Child\'], ProcessFunc) . ‘</li>’;
}
Str .= ‘</ul>’;
return Str;
}
//—————————————————————————
//public String PrintCurrentLevel(String ProcessFunc = ”)
// 对多级分类生成当前位置字符串
// 设如分类数据如下,当前分类为3级分类, 则调用返回 1级分类 -> 2级分类 -> 3级分类
// ├──1级分类
// │
// │
// │
// ├─2级分类
// │ │
// │ └─3级分类
// │
// └─2级分类
//
//
//
//
// @param: ProcessFunc 此为对分类数据如何显示的回调函数,不设置则直接显示分类名称
// 函数定义原型为 function (&arr);
// 其中arr参数为每一个分类信息的一维数组如下:
// array(ID => 1, ParentID => 0, RootID => 0, CategoryName => ’1级分类’)
// 返回值为对上述数据处理的结果,比如返回带链接的分类名字、更改显示颜色等
//
// return value: 返回当前分类在整个分类树中所处位置
//
//—————————————————————————
function PrintCurrentLevel(ProcessFunc = ”)
{
if(!this->CategoryID) return ”;
if(this->_SelfData->Get(“RootID”) == 0)
{
if(ProcessFunc) return ProcessFunc(this->_SelfData->fetchDataToArray());
else return this->_SelfData->Get(“CategoryName”);
}
Current = this->CategoryID;
this->tblObj->SetCondition(‘RootID = ‘ . this->_SelfData->Get(‘RootID’) . ” or ID = ” . this->_SelfData->Get(‘RootID’));
Data = this->tblObj->MapResult(this->tblObj->Select());
return this->_CurrentLevel(Data, Current, ProcessFunc);
}
//—————————————————————————
//public boolean Add(array arr)
// 添加新分类到分类表中
//
// @param: arr 在此数组中包括对新添加分类的定义, 定义如下:
//
// arr[\'RootID\'] 新分类所属的根分类ID
// arr[\'ParentID\'] 新分类的父分类ID
// arr[\'CategoryName\'] 新分类的名称
//
// return value: 返回添加分类操作结果
//
//—————————————————————————
function Add(arr)
{
this->tblObj->SetFields(
Array(
‘RootID’,
‘ParentID’,
‘CategoryName’,
)
);
return this->tblObj->Insert(
Array(
arr[\'RootID\'],
arr[\'ParentID\'],
arr[\'CategoryName\'],
)
);
}
//—————————————————————————
//public boolean Delete(int ID)
// 删除已经存在的分类
//
// @param: ID 要删除的分类ID
//
// return value: 返回删除分类操作结果
//
//—————————————————————————
function Delete(ID)
{
sysOption = &this->KernelRef->Config;
this->tblObj->SetFields(‘*’);
this->tblObj->SetCondition(‘ID = ‘ . (int)ID);
return this->tblObj->Delete();
}
//—————————————————————————
//public boolean Modify(int ID, array arr)
// 修改已经存在的分类
//
// @param: ID 要修改的分类ID
// @param: arr 在此数组中包括修改后的分类定义, 定义如下:
//
// arr[\'RootID\'] 新分类所属的根分类ID
// arr[\'ParentID\'] 新分类的父分类ID
// arr[\'CategoryName\'] 新分类的名称
//
// return value: 返回修改分类操作结果
//
//—————————————————————————
function Modify(ID, arr)
{
this->tblObj->SetCondition(‘ID = ‘ . (int)ID);
prev = this->tblObj->MapOneRow(this->tblObj->Select());
this->tblObj->SetFields(
Array(
‘RootID’,
‘ParentID’,
‘CategoryName’,
)
);
return this->tblObj->Update(arr);
}
//—————————————————————————
//public array Modify(int ID)
// 修改已经存在的分类
//
// @param: ID 指定的分类ID
//
// return value: 返回指定ID分类的信息
// 数组中包括:
// Array(
// ‘ID’ => 分类ID,
// ‘ParentID’ => 父分类ID,
// ‘RootID’ => 根分类ID,
// ‘CategoryName’ => 分类名称,
// );
//
//—————————————————————————
function GetCategory(ID)
{
this->tblObj->SetCondition(‘ID = ‘ . (int)ID);
return this->tblObj->MapOneRow(this->tblObj->Select());
}
}
?>
来源:phpweblog