无限极分类左右值样例

#1 coolcool1265

说是样例,其实没有很好的整理。其中sql语句里用到了$parent[rightvalue]这种数组形式的写法,大家可以尝试$parent.rightvalue形式的写法哈。

希望对大家有帮助。

可以看看jstree中处理无限极目录的方式。

表的结构:
--
-- 表的结构 `spalbum`
--
CREATE TABLE IF NOT EXISTS `spalbum` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parentid` int(3) NOT NULL,
  `name` varchar(11) CHARACTER SET utf8 NOT NULL,
  `leftvalue` int(3) NOT NULL,
  `rightvalue` int(3) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;



  class spalbumModel extends spModel
  {  
    public $pk = "id"; // 数据表的主键  
    public $table = "spalbum"; // 数据表的名称
    public $_rootNodeName="_root_";//根目录,是所有目录的最顶级

//无限极分类的实现
    /**
     * 添加一个节点,返回该节点的 ID
     * @param array $node
     * @param int $parentId
     * @return int
     */
function createNode($node, $parentId) {
        $parentId = (int)$parentId;
        if ($parentId) {
            $parent = $this->find(array('id'=>$parentId));
            if (!$parent) {               
                return false;//没有找到父节点
            }
        } else {
            // 如果 $parentId 为 0 或 null,则创建一个顶级节点
            $parent = $this->find(array('name' => $this->_rootNodeName));
            if (!$parent) {
                // 如果根节点不存在,则自动创建
                $parent = array(
                    'name' => $this->_rootNodeName,
                    'leftvalue' => 1,
                    'rightvalue' => 2,
                    'parentid' => -1,
                );
                if (!$this->create($parent)) {
                    return false;
                }
            }
            // 确保所有 __ROOT_NODE__ 的直接字节点的 parent_id 都为 0
            $parent[$this->pk] = 0;
        }
        // 根据父节点的左值和右值更新数据
        $sql = "update $this->table set leftvalue = leftvalue+2  where leftvalue>= $parent[rightvalue]";
        $this->_db->exec($sql);
        $sql = "update $this->table set rightvalue = rightvalue + 2 where rightvalue >= $parent[rightvalue]";
        $this->_db->exec($sql);
        // 插入新节点记录
        $node = array(
     'parentid' => $parent[$this->pk],
            'name' => $node[name],
            'leftvalue' => $parent[rightvalue],
            'rightvalue' => $parent[rightvalue]+ 1,            
        );   
        return $this->create($node);
    }

/**
     * 删除一个节点及其子节点树
     *
     * @param array $node
     *
     * @return boolean
     */
    function removeNode($node) {
        $span = $node[rightvalue] - $node[leftvalue] + 1;
        $sql = "DELETE FROM $this->table WHERE leftvalue >= $node[leftvalue] " .
               "AND rightvalue <= $node[rightvalue]";
        if (!$this->_db->exec($sql)) {
            return false;
        }
        $sql = "UPDATE $this->table SET leftvalue = leftvalue - $span " .
               "WHERE leftvalue >$node[rightvalue]";
        if (!$this->_db->exec($sql)) {
            return false;
        }
        $sql = "UPDATE $this->table SET rightvalue = rightvalue - $span " .
               "WHERE rightvalue > $node[rightvalue]";
        if (!$this->_db->exec($sql)) {
            return false;
        }
        return true;
    }
/**
     * 删除一个节点及其子节点树
     *
     * @param int $nodeId
     *
     * @return boolean
     */
    function removeByPk($nodeId) {
        $node =$this->find((int)$nodeId);
        if (!$node) {           
            return false;
        }
  return $this->remove($node);
    }
  /**
     * 返回根节点到指定节点路径上的所有节点
     *
     * 返回的结果不包括“__ROOT_NODE__”根节点各个节点同级别的其他节点。
     * 结果集是一个二维数组,可以用 array_to_tree() 函数转换为层次结构(树型)。
     *包括本节点
     * @param array $node
     *
     * @return array
     */
    function getPath($node) {
  $sql="select * from $this->table where leftvalue <= $node[leftvalue] and rightvalue >= $node[rightvalue] order by leftvalue asc";
        $rowset = $this->findSql($sql);
        if (is_array($rowset)) {
            array_shift($rowset);
        }
        return $rowset;
    }
  /**
     * 返回指定节点的直接子节点,同级别的子节点
     *
     * @param array $node
     *
     * @return array
     */
    function getSubNodes($node) {
  $sql="select * from $this->table where parentid = $node[id] order by leftvalue asc";
        return $this->findSql($sql);
    }
     /**
     * 返回指定节点为根的整个子节点树
     *
     * @param array $node
     *
     * @return array
     */
    function getSubTree($node) {
        $sql="select * from $this->table where leftvalue BETWEEN $node[leftvalue] AND $node[rightvalue] order by leftvalue asc";
        return $this->findSql($sql);
    }
    /**
     * 获取指定节点同级别的所有节点
     *
     * @param array $node
     *
     * @return array
     */
    function getCurrentLevelNodes($node) {
        $conditions = array('parentid' => $node['parentid']);
        $sort = 'leftvalue ASC';
        return $this->findAll($conditions, $sort);
    }
    /**
     * 取得所有节点
     *
     * @return array
     */
    function getAllNodes() {
        return $this->findAll('leftvalue > 1', 'leftvalue ASC');
    }
    /**
     * 获取所有顶级节点(既 __ROOT_NODE__ 的直接子节点)
     *
     * @return array
     */
    function getAllTopNodes() {
        $conditions = array('parentid'=>0);
        $sort = 'leftvalue ASC';
        return $this->findAll($conditions, $sort);
    }
     /**
     * 计算所有子节点的总数
     *
     * @param array $node
     *
     * @return int
     */
    function calcAllChildCount($node) {
        return intval(($node[rightvalue] - $node[leftvalue] - 1) / 2);
    }
//无限分类结束
  
}
?>

2010-11-26 10:22:27

#2 lintou

很好,mark

2010-11-26 23:18:44