PHP系統左側菜單欄的管理與實現
在日常的開發工作中,面對後臺的日益增長的業務,以及後期業務的叠代開發,通常會選擇添加菜單欄的形式來擴充業務功能,同樣日益增長的後臺菜單選項也為我們後期的維護,產生了一定的困難性。為此我總結出自己關於左側菜單欄的管理模式或者方法。僅供參考。
在通常的開發中,對菜單欄的生成一般是通過以下幾種方式:
(1)模板文件對變量的遍歷(接下來以thinkPHP5為例)
(2)直接通過PHP進行組裝
關於(2)直接通過PHP進行組裝,不建議這樣做,這樣做會增大PHP代碼與HTML的耦合與黏連,不利於代碼的友好性。接下來著重講解(1)模板文件對變量進行遍歷在一般情況下,我們再設計或者制作後臺的菜單欄的時候,一般會選擇ul標簽和li標簽進行組合,以及進行樣式的設置。來達到菜單的一般性要求,縱觀菜單的制作與設計,菜單欄和列表數據項具有以下幾個特點:
(1)通用性 適應不同屏幕的大小(暫時先不討論響應式布局),在不同的瀏覽器要顯示出相同的效果。
(2)擴展性 在實際的項目中,業務功能不會只有一個或者兩個,會有很多。後期的叠代開發,新業務功能的添加會,都會用到列表項的擴展。
接下來繼續討論具備以上兩種特征的菜單的管理的實現。
1.寫入配置文件
顧名思義,將自己的菜單欄的所有信息,寫入配置文件。
以thinkPHP5為例,只講實現的思想不講具體的代碼。
接下來看PHP配置文件該怎麽寫呢?
‘nav_set‘=>[ [ ‘name‘=>‘用戶管理‘, ‘url‘ =>url(‘/admin/UserManager/getAllUser‘), ‘other‘=>[url(‘/admin/UserManager/getUserDetail‘)], ‘icon‘=>‘fa fa-user-md‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘開倉平倉‘, ‘url‘ =>url(‘/admin/Warehouse/getAllWarehouse‘), ‘icon‘=>‘gi gi-airplane‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘盈利播報‘, ‘url‘ =>url(‘/admin/ProfitBroadcast/profitBroad‘), ‘icon‘=>‘fa fa-bullhorn‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘產品管理‘, ‘url‘ =>url(‘/admin/Product/getAllProduct‘), ‘icon‘=>‘fa fa-product-hunt‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘所有訂單‘, ‘url‘ =>url(‘/admin/Product/getAllProduct‘), ‘icon‘=>‘fa fa-gavel‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘財務管理‘, ‘url‘ =>url(‘/admin/Finance/financeInfo‘), ‘icon‘=>‘fa fa-money‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘編輯規則‘, ‘url‘ =>url(‘/admin/EditRule/edit‘), ‘icon‘=>‘fa fa-pencil-square-o‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], [ ‘name‘=>‘系統設置‘, ‘icon‘=>‘fa fa-gear‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>1, ‘sub‘=>[ [ ‘name‘=>‘提成設置‘, ‘url‘ =>url(‘/admin/SystemSetting/commission‘), ‘icon‘=>‘‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ], [ ‘name‘=>‘金額設置‘, ‘url‘ =>url(‘/admin/SystemSetting/money‘), ‘icon‘=>‘‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ], ] ], [ ‘name‘=>‘賬號設置‘, ‘url‘ =>url(‘/admin/AccountSetting/index‘), ‘icon‘=>‘gi gi-user‘, ‘style‘=>‘color: white‘, ‘state‘=>0, ‘hasSub‘=>0 ], ]
有代碼可以看出,在配置文件裏面寫入的是一個數組,裏面包含的字段:state表示開關,name表示列表項的具體名稱;url表示一個列表項的所鏈接的地址;style表示列表項特有的樣式,hasSub表示是否有子列表。如果有需要還可以裏面繼續添加自己想要的字段。因此我們需要建立一個所有業務的控制器的父控制器Base,在Base的構造方法裏面進行,列表的數據的獲取與添加。Base控制器代碼
class Base extends Controller { public function __construct(Request $request = null) { parent::__construct($request); $clicked_url = \request()->url(); //獲取每次點擊的url $nav_arr = Config::get(‘nav_set‘); //獲取導航配置信息 $nav_arr = getMenu($nav_arr,$clicked_url); //對每個配置項進行狀態設置 $this->assign(‘clicked_url‘,$clicked_url); //對頁面進行賦值 $this->assign(‘nav_list‘,$nav_arr); } }
裏面有一個核心的算法:getMenu($nav_arr,$clicked_url)請看具體代碼的實現
/** * 將所點擊的列表項以及其父列表項的state置1 * * @param $menu_arr 菜單欄配置信息 * @param $url 點擊的鏈接 * @return array|bool */ function getMenu($menu_arr,$url){ if (!is_array($menu_arr)){ return false; } for ($i = 0;$i < count($menu_arr);$i++){ if (array_key_exists(‘url‘,$menu_arr[$i]) && !empty($menu_arr[$i][‘url‘])){ $menu_url = strtolower($menu_arr[$i][‘url‘]); $url = strtolower($url); $menu_url = explode(‘.‘,$menu_url)[0]; $url = explode(‘.‘,$url)[0]; // 比對點擊的url和配置信息中的url是否一致 if (strpos($menu_url,$url) !== false){ $menu_arr[$i][‘state‘] = 1; return $menu_arr; }else{
// 多個url綁定到一個列表項 if (array_key_exists(‘other‘,$menu_arr[$i]) && !empty($menu_arr[$i][‘other‘])){ for ($j = 0;$j < count($menu_arr[$i][‘other‘]);$j++){ $other_url = $menu_arr[$i][‘other‘][$j]; $other_url = explode(‘,‘,strtolower($other_url))[0]; if (strpos($other_url,$url) !== false){ $menu_arr[$i][‘state‘] = 1; return $menu_arr; } } } } }else{ if (array_key_exists(‘sub‘,$menu_arr[$i])){ // 繼續進行遞歸搜索 $sub = getMenu($menu_arr[$i][‘sub‘],$url); if ($sub == $menu_arr[$i][‘sub‘]){ $menu_arr[$i][‘state‘]=0; }else{ $menu_arr[$i][‘state‘]=1; } $menu_arr[$i][‘sub‘] = $sub; } } } return $menu_arr; }
getMenu()這個方法主要進行配置數組的處理,為了增加其擴展性,采用了遞歸的方式進行處理的。
接下請看模板文件的代碼:
<ul class="sidebar-nav" style="color: white;font-size: 17px;"> <volist name="nav_list" id="bar">
<li> <if condition="$bar.hasSub == 1"> <if condition="$bar.state == 1"> <a href="#" class="sidebar-nav-menu open" style="color: white"> <i class="fa fa-chevron-left sidebar-nav-indicator sidebar-nav-mini-hide"></i> <i class="fa fa-gear sidebar-nav-icon"></i> <span class="sidebar-nav-mini-hide">{$bar.name}</span> </a> <else/> <a href="#" class="sidebar-nav-menu" style="color: white"> <i class="fa fa-chevron-left sidebar-nav-indicator sidebar-nav-mini-hide"></i> <i class="fa fa-gear sidebar-nav-icon"></i> <span class="sidebar-nav-mini-hide">{$bar.name}</span> </a> </if> <ul> <volist name="$bar.sub" id="sub_bar"> <li> <if condition="$sub_bar.state == 1"> <a href="{$sub_bar.url}" class="active">{$sub_bar.name}</a> <else/> <a href="{$sub_bar.url}" class="" style="color: white">{$sub_bar.name}</a> </if> </li> </volist> </ul> <else/> <if condition="$bar.state == 1"> <a href="{$bar.url}" class="open" style="{$bar.style}"> <i class="{$bar.icon} sidebar-nav-icon"></i> <span>{$bar.name}</span> </a> <else/> <a href="{$bar.url}" style="{$bar.style}"> <i class="{$bar.icon} sidebar-nav-icon"></i> <span>{$bar.name}</span> </a> </if> </if> </li>
</volist> </ul>
在模板文件內循環加入我們所設置的信息,最終效果如下圖
2.寫入數據庫
關於寫入數據庫方式,通常不是用來作為功能菜單了,類似淘寶、京東首頁左側商品列表,為此我們需要建立相關的表來存放這些商品和商品的類別,並且還要考慮後期的擴展,假如雙十一或者618他們的列表項是不一樣的。本次我麽只討論功能性列表的管理,對此不再贅述。
PHP系統左側菜單欄的管理與實現