PHP无限分类代码 做好事不留名 就是这么任性

好久没有更新BLOG 这次又发布一个关于分类操作的代码

有啥好处自己看 把代码拷贝下来自己测试吧 欢迎交流 拍砖



无限分类主题代码文件 CacheCategory.class.php


<?php
class CacheCategory {
    
    public $data = array();
    public $fileName = '';
    
    /**
     * 设置文件名 用于存放缓存分类数据
     * @param type $fileName 绝路文件地址
     * @return type 设置成功返回文件地址 设置失败返回false
     */
    public function setFileName($fileName) 
    {
        if (!file_exists($fileName)) {
            return false;
        }
        return $this->fileName = $fileName;
    }
    
    /**
     * 写缓存数据
     * 会做二维数组校验 必须传入二维数组
     * @param type $data 二维数组
     * @return boolean 写成功返回 true 失败返回 false
     */
    public function writeCache($data) 
    {
        $fileName = $this->fileName;
        if (!file_exists($fileName)) {
            return false;
        }
        if (!is_array($data)) {
            return false;
        }
        $count = count($data);
        $n = 0;
        foreach($data as $k => $v) {
            if (isset($v['id']) && isset($v['pid'])) {
                $n++;
                $formatData[$v['id']] = $v;
            }
        }
        unset($data);
        if ($count != $n) {
           return false;
        }
        if (file_put_contents($fileName, json_encode($formatData))) {
           $this->data['origin'] = $formatData;
           return true;
        }
        return false;
    }
    
    /**
     * 向下移动分类
     * @param type $id 当前分类的id
     * @return boolean 移动失败 返回false 成功返回true
     */
    public function moveDown($id)
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return false;
        }
        if (!isset($origin[$id])) {
            return false;
        }
        $self = $origin[$id];
        $broArray  = array();
        foreach ($origin as $k => $v) {
            if ($self['pid'] == $v['pid'] && $self['id'] 
                              != $v['id'] && $self['px'] > $v['px']) {
                $broArray[] = $v;
            }
        }
        if (empty($broArray)) {
            return false;
        }
        $broArray = $this->categorySort($broArray, 'px');
        $broArray = array_shift($broArray);
        $origin[$self['id']]['px'] = $broArray['px'];
        $origin[$broArray['id']]['px'] = $self['px'];
        if (file_put_contents($this->fileName, json_encode($origin))) {
            $this->data['origin'] = $origin;
            return true;
        }
        return false;
    }
    
    /**
     * 向上移动分类
     * @param type $id 当前分类id
     * @return boolean 成功返回true 失败返回false
     */
    public function moveUp($id)
    {
        $origin = $this->getData();
        if (!$origin) {
            return false;
        }
        if (!isset($origin[$id])) {
            return false;
        }
        $self = $origin[$id];
        $broArray  = array();
        foreach ($origin as $k => $v) {
            if ($self['pid'] == $v['pid'] && $self['id'] 
                              != $v['id'] && $self['px'] < $v['px']) {
                $broArray[] = $v;
            }
        }
        if (empty($broArray)) {
            return false;
        }
        $broArray = $this->categorySort($broArray, 'px', '1');
        $broArray = array_shift($broArray);
        $origin[$self['id']]['px'] = $broArray['px'];
        $origin[$broArray['id']]['px'] = $self['px'];
        if (file_put_contents($this->fileName, json_encode($origin))) {
            $this->data['origin'] = $origin;
            return true;
        }
        return false;
    }
    
    /**
     * 添加分类
     * 传入一个一维数组 同时会检测id 和pid的健是否存在
     * @param type $array
     * @return boolean
     */
    public function add($array)
    {
        if (!is_array($array)) {
            return false;
        }
        if (!isset($array['id']) || !isset($array['pid'])) {
           return false; 
        }
        $origin = $this->getData();
        
        if (empty($origin)) {
            return false;
        }
        if (isset($origin[$array['id']])) {
           return false; 
        }
        $origin[$array['id']] = $array;
        if (file_put_contents($this->fileName, json_encode($origin))) {
           $this->data['origin'] = $origin;
           return true;
        }
        return false; 
    }
    
    /**
     * 删除一个分类
     * @param type $id
     * @return boolean
     */
    public function remove($id)
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return false;
        }
        if (!isset($origin[$id])) {
           return false; 
        }
        if ($this->isHaveSon($id)) {
           return false; 
        }       
        unset($origin[$id]);    
        if (file_put_contents($this->fileName, json_encode($origin))) {
            $this->data['origin'] = $origin;
            return true;
        }
        return false;
    }
    
    /**
     * 更新一个分类 传入一个一维数组
     * 必须在数组中有当前分类的id
     * @param type $data
     * @return boolean
     */
    public function update($data)
    {
        if (!isset($data['id'])) {
            return false;//错误的参数数据
        }
        $origin = $this->getData();
        if (empty($origin)) {
            return false;//空数据
        }  
        $origin[$data['id']] = array_merge($origin[$data['id']],$data);
        if (file_put_contents($this->fileName, json_encode($origin))) {
           $this->data['origin'] = $origin;
           return true; 
        }
        return false;
    }
    
    /**
     * 获取所有分类数据 
     * 已经排号序的 新数据靠前展示
     * @return boolean
     */
    public function getAll() 
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return false;
        }
        $data = $this->categorySort(array_values($origin), 'px');
        $this->recursion($data,'all',0);
        if( isset($this->data['all'])) {
            return $this->data['all'];
        }
        return false;
    }
    
    /**
     * 根据指定$id获取子孙分类
     * @param type $id 传入一个指定id
     * @return boolean 成功返回子孙分类列表 失败返回false
     */
    public function getChildren($id)
    {       
        $origin = $this->getData();
        if (empty($origin)) {
            return false;
        }
        $data = $this->categorySort(array_values($origin), 'px');
        $this->recursion($data, $id, $id);
        if (isset($this->data[$id])) {
            return $this->data[$id];
        }
        return false;
    }
    
    /**
     * 根据$id获取自己的分类数据
     * @param type $id
     * @return boolean
     */
    public function getSelf($id)
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return array();
        }
        if (isset($origin[$id])) {
            return $origin[$id];
        }
        return false;
    }
    
    /**
     * 获取父分类的数据
     * @param type $id
     * @return boolean
     */
    public function getFather($id)
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return array();
        }
        if (!isset($origin[$id])) {
            return false;
        }
        $self = $origin[$id];
        foreach ($origin as $k => $v) {
            if ($v['id'] == $self['pid']) {
                return $v;
            }
        }
        return false;
    }
    
    /**
     * 获取祖先分类
     * @param type $id
     * @return boolean
     */
    public function getAncestors($id)
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return array();
        }
        if (!isset($origin[$id])) {
            return false;
        }
        $self = $origin[$id];
        $ancestors = $this->recursionAncestors($origin, $self['pid'], $id);
        $count = count($ancestors);
        $reversion = array();
        for ($i=0; $i < $count; $i++) {
            $tmpArray = array_pop($ancestors);
            $reversion[$tmpArray['id']] = $tmpArray;
        }
        return $reversion;
    }
    
    /**
     * 该递归获取祖先分类
     * @staticvar array $ancestors
     * @param type $origin
     * @param type $pid
     * @param type $id
     * @return type
     */
    protected function recursionAncestors($origin, $pid, $id)
    {
        static $ancestors = array();
        foreach ($origin as $k => $v) {
            if($v['id'] == $pid) {
                $ancestors[$id][$k] = $v; 
                $this->recursionAncestors($origin,$v['pid'],$id);
            }  
        }
       return $ancestors[$id];
    }
    
    /**
     * 获取缓存数据源
     * 如果已经读取 从当前对象内部返回 否则从文件读取返回
     * @return type 成功返回缓存数据源 失败返回 文件内部读取失败时的 false
     */
    protected function getData()
    {
        if (isset($this->data['origin'])) {
            return $this->data['origin'];
        }
        $origin = $this->getCacheData($this->fileName);
        $this->data['origin'] = $origin; 
        return $origin;
    }
    
    /**
     * 检测一个分类是否有子分类
     * @param type $id
     * @return boolean
     */
    protected function isHaveSon($id) 
    {
        $origin = $this->getData();
        if (empty($origin)) {
            return false;
        }
        
        if (!isset($origin[$id])) {
           return false; 
        }
        
        foreach ($origin as $k => $v) {
            if ($v['pid'] == $id) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 读取缓存文件
     * @param type $fileName
     * @return boolean 成功返回数据 失败返回false
     */
    protected function getCacheData($fileName)
    {
        if (!file_exists($fileName)) {
            return false;
        }
        $origin = json_decode(file_get_contents($fileName), true);
        if (!empty($origin)) {
            return $origin;
        }
        return false;
    }
    
    /**
     * 二维数组冒泡排序 默认从大到小
     * @param type $array 二维数组
     * @param type $px 针对排序的字段
     * @param type $type 默认0 从大到小 设置为1 从小到大
     * @return type
     */
    protected function categorySort($array, $px, $type = 0)
    {
        $len = count($array);
        for ($i = 0; $i < $len - 1; $i++) {
            for ($j = $i + 1; $j < $len; $j++) {
                if ($type == 1) {
                    if ($array[$i][$px] > $array[$j][$px]) {
                        $tmp = $array[$i];
                        $array[$i] = $array[$j];
                        $array[$j] = $tmp;
                    }
                } else {
                    if ($array[$i][$px] < $array[$j][$px]) {
                        $tmp = $array[$i];
                        $array[$i] = $array[$j];
                        $array[$j] = $tmp;
                    }
                }
            }
        }
        return $array;
    }
    
    /**
     * 获取当前分类位于多少层 默认返回从1开始 层次+1返回
     * @param type $id
     * @param type $data
     * @return type
     */
    protected function getLevel($id, $data)
    {
        $level = 0;
		foreach($data as $key => $value){
			if ($value['id'] == $id) {
				$level++;
				$level += $this->getLevel($value['pid'], $data);
			}
		}
		return $level;
	}
    
    /**
     * 递归分类
     * @param type $array 二维数组
     * @param type $key 存放的数据键名称
     * @param type $pid 根据pid返回不同的分类数据
     */
    protected function recursion($array, $key, $pid)
    {
        foreach ($array as $k => $v) {
            if ($v['pid'] == $pid) {
               $v['level'] = $this->getLevel($v['pid'], $array) + 1;
               $this->data[$key][$v['id']] = $v;
               $this->recursion($array, $key, $v['id']);      
            } 
        }
    }
} 

演示代码

<?php
require dirname(__FILE__) . '/CacheCategory.class.php';
header('Content-type:text/html;charset=utf8');
$md5Name = md5('文章分类');
$cacheFileName = dirname(__FILE__) . "/Cache/{$md5Name}.json.category.cache";
$c = new CacheCategory();
$c->setFileName($cacheFileName);
$c->writeCache(getData());
//$c->moveDown(19);
//$c->moveUp(19);
//$c->add(array('id'=>'20','name'=>'20000','pid'=>'8','px'=>'20')); 
//$c->update(array('id'=>'19','name'=>'666'));

$data = $c->getAll();
foreach ($data as $k => $v) {
  echo $v['level'],str_repeat('  ',$v['level']),'---',
       $v['id'], '--',$v['name'],'--',$v['pid'],'--',$v['px'],'<br />';
}
echo '<br />';

//$c->remove(9);//完成
$data = $c->getChildren(7);

foreach ($data as $k => $v) {
  echo $v['level'],str_repeat('  ',$v['level']),'---',
       $v['id'], '--',$v['name'],'--',$v['pid'],'--',$v['px'],'<br />';
}

//$data = $c->getAncestors(19);
//print_R($data);
//$data = $c->getSelf(19);
//print_R($data);
//
//$data = $c->getFather(19);
//$data = $c->getFather(19);
//
//print_R($data);
//$data = $c->getFather(13);
//print_R($data);

//模拟数据库中返回的数据进行测试
 function getData() {
        $data = array(
            array('id'=>'1','name'=>'aaaaa','pid'=>'0','px'=>'1'),
            array('id'=>'2','name'=>'bbbbb','pid'=>'1','px'=>'2'),
            array('id'=>'3','name'=>'ccccc','pid'=>'1','px'=>'3'),
            array('id'=>'4','name'=>'ddddd','pid'=>'3','px'=>'4'),
            array('id'=>'5','name'=>'eeeee','pid'=>'0','px'=>'5'),
            array('id'=>'6','name'=>'fffff','pid'=>'5','px'=>'6'),
            array('id'=>'7','name'=>'ggggg','pid'=>'5','px'=>'7'),
            array('id'=>'8','name'=>'hhhhh','pid'=>'0','px'=>'8'),
            array('id'=>'9','name'=>'iiiii','pid'=>'7','px'=>'9'),
            array('id'=>'10','name'=>'jjjjj','pid'=>'9','px'=>'10'),
            array('id'=>'11','name'=>'kkkkk','pid'=>'10','px'=>'11'),
            array('id'=>'12','name'=>'lllll','pid'=>'1','px'=>'12'),
            array('id'=>'13','name'=>'mmmmm','pid'=>'5','px'=>'13'),
            array('id'=>'14','name'=>'nnnnn','pid'=>'6','px'=>'14'),
            array('id'=>'15','name'=>'ooooo','pid'=>'14','px'=>'15'),
            array('id'=>'16','name'=>'ppppp','pid'=>'8','px'=>'17'),
            array('id'=>'17','name'=>'qqqqq','pid'=>'8','px'=>'16'),
            array('id'=>'18','name'=>'rrrrr','pid'=>'10','px'=>'18'),
            array('id'=>'19','name'=>'sssss','pid'=>'10','px'=>'19'),
        );
        return $data;
}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值