作用:
由一维数组,数组中至少包含 id和pid两个字段,来构建一个树形结构的数组,用于构建分类树。
代码:
class classifyBuild{
private $result;//结果数组
private $arrSource;//待处理数组
public $sort = false;
public function __construct(array $arrSource)
{
$this->arrSource = $arrSource;
$this->result = array();
}
/**
* 在数组$arr一维上查找是否 id 值和$id相同的值
* @param [array] $arr [结果数组]
* @param [int] $id [要查找的id值]
* @return [int|null] [如果存在,则返回该值对应的位置$key;否则,返回null]
*/
private function search($id)
{
foreach($this->result as $key=>$value){
if ($value['id'] == $id) {
return $key;
}
}
return null;
}
/**
* 在结果数组中是否有 id值和$pid相同的值
* @param [array] $arr [结果数组]
* @param [int] $pid [要查找的pid值]
* @return [&$arr|&$pid] [如果存在,则返回结果数组中查找到的该值的引用;如果不存在,则返回$pid的引用]
*/
private function updateArray(&$result, $arrTmp)
{
foreach($result as $key=>$one){
if ($one['id'] == $arrTmp['pid']) {
//$result[$key]['childrens'][] = $arrTmp;
$this->result_push($result[$key]['childrens'], $arrTmp);
return true;
} elseif (!empty($one['childrens'])) {
$returnValue = $this->updateArray($result[$key]['childrens'], $arrTmp);
if (true === $returnValue) {
return true;
}
}
}
return false;
}
public function make(){
foreach($this->arrSource as $posi=>$oneArr){
$arrTmp = array();
/**
* 处理当前节点
* 判断 当前节点在结果数组中是否存在;
* 存在,则将当前节点挂载到结果数组的childrens中;
* 否则,为父节点生成一个节点,将当前节点挂载在父节点的childrens上,将父节点挂载到结果数组中
*/
$key = $this->search($oneArr['id']);
if (!is_null($key) && 0==$oneArr['pid']) {
//如果存在本次查找的对象,但是当前对象的pid是0,则说明当前节点没有父节点,而且已经因为在之前被挂载过了,无需再处理
continue;
} elseif (!is_null($key)) {
//如果在结果数组中已经存在id值,单当前节点对象pid不是0,则说明当前节点还有父节点,则取出这个id值,消掉数组中的对应的值
$arrTmp = $oneArr;
$arrTmp['childrens'] = $this->result[$key]['childrens'];
unset($this->result[$key]);
} else {//如果在结果数组中不存在对应的id值
$arrTmp = $oneArr;
$arrTmp['childrens'] = array();
}
/**
* 将处理过的当前节点 $arrTmp 根据不同的情况更新到结果数组中
*/
if (0!=$arrTmp['pid']) {
//如果父id不是0,则更新当前数组到结果数组中
if ( false === $this->updateArray($this->result, $arrTmp)) {//如果更新不成功,说明是没有被收录的父id
$arrTmp = array('id'=>$arrTmp['pid'], 'pid'=>0 , 'childrens'=>array($arrTmp));
//array_push($this->result, $arrTmp);
$this->result_push($this->result, $arrTmp);
}
} else {
//父节点为0,说明当前节点没有父节点,应该挂载在结果数组一维上
//array_push($this->result, $arrTmp);
$this->result_push($this->result, $arrTmp);
}
}
}
/**
* 将需要插入的数据更新到结果数组中
* @param [array] $arr [结果数组]
* @param [array] $pushValue [需要插入的数组]
*/
private function result_push(&$arr, $pushValue)
{
if (false === $this->sort) {//未开启sort
$arr[] = $pushValue;
} else {//开启sort
$length = 0;
foreach($arr as $one){
$one['sort'] = isset($one['sort'])?$one['sort']:0;
$pushValue['sort'] = isset($pushValue['sort'])?$pushValue['sort']:0;
if ($one['sort'] > $pushValue['sort']) {
break;
} else {
$length++;
}
}
$before = array_slice($arr, 0, $length);
$after = array_slice($arr, $length, count($arr)-$length);
$arr = array_merge($before, array($pushValue), $after);
}
}
public function getResult()
{
return $this->result;
}
}
测试数据:
$arrSource = array(
array(
'id'=>4,
'pid'=>1,
'sort'=>1
),
array(
'id'=>6,
'pid'=>0,
'sort'=>8
),
array(
'id'=>3,
'pid'=>1,
'sort'=>2
),
array(
'id'=>12,
'pid'=>0,
'sort'=>3
),
array(
'id'=>2,
'pid'=>1,
'sort'=>3
),
array(
'id'=>13,
'pid'=>2,
'sort'=>2
),
array(
'id'=>16,
'pid'=>4,
'sort'=>1
),
array(
'id'=>5,
'pid'=>6,
'sort'=>3
),
array(
'id'=>18,
'pid'=>2,
'sort'=>8
),
array(
'id'=>15,
'pid'=>2,
'sort'=>0
),
array(
'id'=>14,
'pid'=>12,
'sort'=>2
),
array(
'id'=>17,
'pid'=>12,
'sort'=>1
),
array(
'id'=>11,
'pid'=>12,
'sort'=>3
),
array(
'id'=>1,
'pid'=>0,
'sort'=>2
),
array(
'id'=>8,
'pid'=>7,
'sort'=>4
),
array(
'id'=>10,
'pid'=>6,
'sort'=>8
),
array(
'id'=>9,
'pid'=>6,
'sort'=>24
),
array(
'id'=>7,
'pid'=>0,
'sort'=>82
),
array(
'id'=>24,
'pid'=>20,
'sort'=>523
),
array(
'id'=>26,
'pid'=>20,
'sort'=>2
),
array(
'id'=>22,
'pid'=>20,
'sort'=>1
),
array(
'id'=>20,
'pid'=>18,
'sort'=>6
),
);
用法:
$classify = new classifyBuild($arrSource);
$classify->sort = true;
$classify->make();
dump($classify->getResult());