好久没有更新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;
}