PHPでの木を見る

こんにちは、実際、サンドボックスからのこのメッセージに応えてこの投稿を書くことにしました。

私は自分がプログラミングのプロだとは思いませんが、時には本当にやりたいと思うこともありますが、それでも、この方法でツリーを構築するのは間違っていると思います。

コメントツリーではなく、メニューツリーを作成します。 メニューを作成する私の方法は、変更やコメントツリーの作成が簡単です。 メニューには、任意の数のサブメニューを含めることができます。 私のメニューテーブル構造は次のとおりです。



m_Id

m_Position

m_LineId

m_ParentId

m_Type

m_Title

m_Description

m_Data









木を建てることに戸惑い、自分で考えるのが面倒だったので、これらのタイネットの既製のソリューションを探すことにしました。 既製のソリューションのようなものですが、これらの既製のソリューションは、私に合わないフレームワークで実装されました。残りは、データベースクエリの束でツリーが構築されました。 、そして、あらゆる種類のCOUNT()およびその他のがらくたを伴う倒錯なしに。 時間を無駄にせず、メニューツリーを構築するクラスのコードを提供します。

 class MenuFactory extends BaseClass { /** * * var mixed        */ public $MenuTree; /** * * @var mixed       , .. ,      */ public $MenuList; private $level=0; /** * * @param int Id     * @param int/bool  bool==true -      ,     .  ,          * @return mixed */ public function GetMenu($menu_id, $return_as_list = false) { //         $this->sql->Query("SELECT * FROM `menus` WHERE `m_LineId`=?d ORDER BY m_Position, m_ParentId", $menu_id); // $this->MenuList = array(); $ml = array(); while($r = $this->sql->Assoc()) { //    MenuItem    $m = CommonUtils::ObjectFromArray('MenuItem', CommonUtils::DelPrefix($r,'m_')); //       $this->MenuList[] = $m; //      ,        $ml[] = clone $m; } //  $return_as_list == true       if(is_bool($return_as_list) && $return_as_list) { return $this->MenuList; } // ,  $return_as_list == false    else if(!$return_as_list) { $this->MenuTree = array(); $this->MenuTree = $this->GetMenuChilds(0,$ml); return $this->MenuTree; } // ,  $return_as_list == ,      ,    else if(is_numeric($return_as_list)) { $this->MenuTree = array(); $this->MenuTree = $this->GetMenuChilds(0,$ml, $return_as_list); return $this->MenuTree; } //print_r($this->menuTree); } /** * * @param int $p_id Id    * @param mixed $menuList   ,        * @param int $levels   * @return mixed      */ private function GetMenuChilds($p_id, $menuList, $levels = null) { //     ,     $a = array(); //     foreach($menuList as $item) { //TODO: Optimize code //  ParentId       id, // ,      .    if($item->ParentId == $p_id) { $this->level++; //  $levels ,     $this->levels, //        ,  $levels if($levels != null && $this->level <= $levels) { //       .        // $this->MenuList   , ParentId   id   , // ,       $item->ChildMenus = $this->GetMenuChilds($item->Id, $menuList, $levels); //          $this->level $item->Level = $this->level; //      $a[] = $item; } else { //           $this->MenuList $item->ChildMenus = $this->GetMenuChilds($item->Id, $menuList); $item->Level = $this->level; } $this->level--; // $levels  ,  ParentId     ,   //  ,        if($levels == null) { $a[] = $item; } } } //      return $a; } /** * * @return mixed      */ public function GetMenuList() { return $this->MenuList; } /** * * @param int $menu_id Id  ,        * @return mixed    */ public function GetMenuPathTo($menu_id) { //      ,      //  ,     .    $a = array(); for($i=0; $i<count($this->MenuList); $i++) { //      id  id   if($this->MenuList[$i]->Id == $menu_id) { //     $a[] = $this->MenuList[$i]; //      ,     , //    $menu_id  ,  id    $menu_id = $this->MenuList[$i]->ParentId; // ,  ) $i=-1; } } //        -> , //  ,         :  ->  return array_reverse($a); } /** * * @param int $menu_id Id ,     * @return MenuItem   */ public function GetMenuById($menu_id) { $this->sql->Query("SELECT * FROM `menus` WHERE `m_Id`=?d LIMIT 1", $menu_id); $record = $this->sql->Assoc(); if($record) { $record = CommonUtils::DelPrefix($record,'m_'); return CommonUtils::ObjectFromArray('MenuItem', $record); } return null; } }
      
      







メニュー項目を表すクラスのコード:

 class MenuItem { public $Id; public $Position; public $ParentId; public $LineId; public $Type; public $Title; public $Description; public $Data; public $Level; public $ChildMenus; }
      
      







PHPコードを強調表示する方法はわかりませんが、それについては知りません。

原則として、 GetMenu()メソッドを使用すると、メニューツリーとメニューの両方をリストとして取得できることは明らかです。 さらに、2番目の引数として0から無限大までの数値を指定すると、メニューツリーはこの数値に等しい深さでロードされます。



GetMenuPathTo()メソッド 、IDがパラメーターとして渡されるメニュー項目へのパスを探します。このメソッドは、サイト上のパンくずリストを整理するために実装されました



CommonUtils :: DelPrefix()を使用すると、連想配列のプレフィックスを削除して、メニュー項目のプロパティの実際の名前を取得できます。

CommonUtils :: ObjectFromArray()は、それに割り当てられたクラスのオブジェクトを返します。このオブジェクトには、2番目のパラメーターで渡された連想配列の値が設定されます。



誰かがこのコードを気に入らないかもしれないとは言いませんが、データベースへの1回のクエリで、メニューツリーを構築するのに非常に役立ちます。



すべて成功。



upd :// kamentyを「木を構築するために%% methodname%が機能しなかった理由」または「なぜmethodname%を使用しなかったのですか?」というスタイルで去るすべての人に私は厳declareに宣言します。 実装をもたらしました。 おそらくあなたのmethodname%を知らなかったでしょう。 いずれにせよ、あなたのコメントは私にとって重要であり、十分な注意なしに残されません。



All Articles