PHP無限分類(樹形類)の深い分析

9173 ワード

PHP无限分类、Googleはすぐに多くの関连资料を见つけることができて、考え方は比较的に风を引いて、同じく比较的に多いのは分类表に少なくともid、pid、nameの3つのフィールドがあって、idは自増表分类して、pidは父分类して、nameは分类名で、このように1本の木を构成して、下のように、私が分类表を调べて得た结果集です.
 
  
// PHP
return array(
    array(
        'id'=>1,
        'pid'=>0,
        'name'=>' '
    ),
    array(
        'id'=>2,
        'pid'=>0,
        'name'=>' '
    ),
    array(
        'id'=>3,
        'pid'=>0,
        'name'=>' '
    ),
    array(
        'id'=>4,
        'pid'=>0,
        'name'=>' '
    ),
    array(
        'id'=>5,
        'pid'=>0,
        'name'=>' '
    ),
    array(
        'id'=>6,
        'pid'=>2,
        'name'=>' '
    ),
    array(
        'id'=>7,
        'pid'=>2,
        'name'=>' '
    ),
    array(
        'id'=>8,
        'pid'=>6,
        'name'=>' '
    ),
    array(
        'id'=>9,
        'pid'=>3,
        'name'=>' '
    ),
    array(
        'id'=>10,
        'pid'=>3,
        'name'=>' '
    ),
    array(
        'id'=>11,
        'pid'=>3,
        'name'=>' '
    ),
    array(
        'id'=>12,
        'pid'=>9,
        'name'=>' '
    ),
    array(
        'id'=>13,
        'pid'=>9,
        'name'=>' '
    ),
    array(
        'id'=>14,
        'pid'=>9,
        'name'=>' '
    ),
    array(
        'id'=>15,
        'pid'=>12,
        'name'=>' '
    ),
    array(
        'id'=>16,
        'pid'=>12,
        'name'=>' '
    ),
    array(
        'id'=>17,
        'pid'=>12,
        'name'=>'MP3 '
    ),
    array(
        'id'=>18,
        'pid'=>17,
        'name'=>'128K'
    ),
    array(
        'id'=>19,
        'pid'=>8,
        'name'=>' '
    ),
    array(
        'id'=>20,
        'pid'=>11,
        'name'=>' '
    ),
    array(
        'id'=>21,
        'pid'=>11,
        'name'=>' '
    ),
);
?>

風を引くのは風を引くが,それらの文章が提供する無限分類のクラス関連操作は少し挫折し,データベース操作も直接カプセル化した.つまり他の人があなたのこの種類を使うので、またあなたと同じ時計を建てなければならなくて、本当に気持ち悪いです.プロジェクトが使用されるため、PHPが無限に分類されたクラス(ツリークラスとも呼ばれる)を自分で書き、データベースの操作がなく、インスタンス化するときに結果セット、すなわちツリー配列を伝えるだけです.leafメソッドまたはnaviメソッドを実行すると、希望の結果が得られます.次に、ソースコードを見て、smartyテンプレートエンジンの対応するテンプレート再帰メソッドを奉納してください.
 
  
/**
 * Tree ( )
 *
 * @author Kvoid
 * @copyright http://kvoid.com
 * @version 1.0
 * @access public
 * @example
 *   $tree= new Tree($result);
 *   $arr=$tree->leaf(0);
 *   $nav=$tree->navi(15);
 */
class Tree {
    private $result;
    private $tmp;
    private $arr;
    private $already = array();
    /**
     *
     *
     * @param array $result
     * @param array $fields ,array( id, id)
     * @param integer $root id
     */
    public function __construct($result, $fields = array('id', 'pid'), $root = 0) {
        $this->result = $result;
        $this->fields = $fields;
        $this->root = $root;
        $this->handler();
    }
    /**
     *
     */
    private function handler() {
        foreach ($this->result as $node) {
            $tmp[$node[$this->fields[1]]][] = $node;
        }
        krsort($tmp);
        for ($i = count($tmp); $i > 0; $i--) {
            foreach ($tmp as $k => $v) {
                if (!in_array($k, $this->already)) {
                    if (!$this->tmp) {
                        $this->tmp = array($k, $v);
                        $this->already[] = $k;
                        continue;
                    } else {
                        foreach ($v as $key => $value) {
                            if ($value[$this->fields[0]] == $this->tmp[0]) {
                                $tmp[$k][$key]['child'] = $this->tmp[1];
                                $this->tmp = array($k, $tmp[$k]);
                            }
                        }
                    }
                }
            }
            $this->tmp = null;
        }
        $this->tmp = $tmp;
    }
    /**
     *
     */
    private function recur_n($arr, $id) {
        foreach ($arr as $v) {
            if ($v[$this->fields[0]] == $id) {
                $this->arr[] = $v;
                if ($v[$this->fields[1]] != $this->root) $this->recur_n($arr, $v[$this->fields[1]]);
            }
        }
    }
    /**
     *
     */
    private function recur_p($arr) {
        foreach ($arr as $v) {
            $this->arr[] = $v[$this->fields[0]];
            if ($v['child']) $this->recur_p($v['child']);
        }
    }
    /**
     *
     *
     * @param integer $id id
     * @return array ,
     */
    public function leaf($id = null) {
        $id = ($id == null) ? $this->root : $id;
        return $this->tmp[$id];
    }
    /**
     *
     *
     * @param integer $id id
     * @return array
     */
    public function navi($id) {
        $this->arr = null;
        $this->recur_n($this->result, $id);
        krsort($this->arr);
        return $this->arr;
    }
    /**
     *
     *
     * @param integer $id id
     * @return array leaf id
     */
    public function leafid($id) {
        $this->arr = null;
        $this->arr[] = $id;
        $this->recur_p($this->leaf($id));
        return $this->arr;
    }
}
?>

smartyでのPHP無限分類の使い方:
$result=$db->query(……);//ここでクエリは結果セットを取得し、結果セットが配列であることに注意します.
$tree= new Tree($result);
$arr=$tree->leaf(0);
$nav=$tree->navi(15);
$smarty->assign(‘arr',$arr);
$smarty->assign(‘nav',$nav);
$smarty->display(‘test.html');
smartyテンプレートでは、次のように再帰されます.
 
  





もちろん、再帰方法を変更して、あなたの考えているラベルで拘束されません.HTML+PHPミックスの再帰方法ここでは貼らないし、私も書くのがおっくうで、ミックスが大嫌いで、見ていて気持ち悪いので、ここでjake先輩のSpeedPHPフレームワークをお勧めします.デフォルトのエンジンはsmartyなので、私のこのPHP無限分類はSPフレームワークと完全に互換性があります.同様に、jqueryのtreeviewプラグインとドロップダウンメニュープラグインも完璧にサポートされています.
ところで、Smartyの強力なキャッシュ機能を使うことをお勧めします.キャッシュこそ王道です.