本文實(shí)例講述了tp5框架前臺(tái)無(wú)限極導(dǎo)航菜單類實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:
適用于 id name pid sort 類似結(jié)構(gòu)的表結(jié)構(gòu)
使用方法:(tp5)
1、將最下面的代碼保存到“前臺(tái)”控制器目錄下(名為 FrontNav.php),比如(路徑): application/index/controll(應(yīng)用/模塊/控制器)
2、在控制器中使用:(application/index/controll/index)(應(yīng)用/模塊/控制器/方法)
也可以放到基礎(chǔ)類的初始化方法中,如:Base.php 的 _initialize() 方法(不用多解釋,這個(gè)是 tp5 的初始化方法 貌似 init() 也行?可以自己試試)
使用:
1)、第一步:先實(shí)例化本類, 5 個(gè)參數(shù)。
參數(shù)說(shuō)明:
- param 1:必填 字符串類型 數(shù)據(jù)表名稱(也是模型名稱),不用其實(shí)字母大寫也行。例如: category
- param 2:選填 字符串類型 模型所在的路徑(默認(rèn)是:admin模塊下的model目錄)。如果你不叫 admin,那么書寫格式如下:houtai/model
- param 3:必填 字符串類型 父級(jí)欄目字段名稱,例如:pid(parent id)
- param 4:選填 數(shù)組類型 默認(rèn)是按 id 正序排序的,如果有排序字段 sortField 的值為 字段名稱 如 sort 或者 listorder 等…,sortOrder 的值為 asc(正序) 或 desc (倒序),建議按這個(gè)排序,要不然會(huì)顯示有點(diǎn)亂,因?yàn)闄?quán)重的關(guān)系需要手動(dòng)排序顯示的位置。
- param 5:必填 二維數(shù)組 替換關(guān)鍵詞,該參數(shù)的第一個(gè)數(shù)組為頂部導(dǎo)航所需要替換的關(guān)鍵詞(必填),linkUrl(url 鏈接)是固定模式,必須這么寫,它的值是:模塊/控制器/方法,其他的鍵為要替換的關(guān)鍵詞值為字段名稱。第二個(gè)數(shù)組(選填)為二級(jí)菜單,第三個(gè)數(shù)組(選填)為N級(jí)菜單,此三個(gè)數(shù)組個(gè)數(shù)要對(duì)應(yīng) $this->createNavHtml() 方法中模版參數(shù)的個(gè)數(shù),詳見(jiàn) createNavHtml() 方法解釋。
$frontNav = new FrontNav('category', '', 'pid', array(
'sortField' => 'sort',
'sortOrder' => 'asc'
), array(
array(
'linkUrl' => 'index/artlist/index',
'catName' => 'name',
'catDesc' => 'desc'
),
array(
'linkUrl' => 'index/artlist/index',
'catName' => 'name',
'catDesc' => 'desc'
)
));
2)、第二步:生成 導(dǎo)航的 html 結(jié)構(gòu),4個(gè)參數(shù)
- param 1:選填 字符串類型 首頁(yè)的 html 模版,例如 ‘li>a class=”navi_home” href=”/”>首頁(yè)/a>/li>'
- param 2:必填 數(shù)組類型 頂部導(dǎo)航的 html 模版,注意下面實(shí)例的格式寫法
- param 3:選填 數(shù)組類型 二級(jí)菜單的 html 模版,同上
- param 4:選填 數(shù)組類型 N級(jí)菜單的 html 模版,同上
$navHtml = $frontNav->createNavHtml('li>a class="navi_home" href="/" rel="external nofollow" rel="external nofollow" >首頁(yè)/a>/li>', array(
'ul id="jsddm" class="topNav">',
'li>a href="linkUrl" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" title="catDesc">catName/a>',
'/li>',
'/ul>'
), array(
'ul class="twoLevel">',
'li>a href="linkUrl" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" title="catDesc">catName/a>',
'/li>',
'/ul>'
), '');
3)、第三步:向模版輸出
$this->assign(array(
'navHtml' => $navHtml
));
4)、第四步:模版調(diào)用(多余??)
div id="navi">
{$navHtml}
/div>
提示:
1、替換關(guān)鍵詞參數(shù)個(gè)數(shù)與模版(除了首頁(yè)外)參數(shù)個(gè)數(shù)一定要對(duì)應(yīng),打字解釋的可能有點(diǎn)不明白,詳細(xì)的對(duì)照 實(shí)例化 和 創(chuàng)鍵方法 的代碼看幾遍就明白了,實(shí)在不行可以看源程序,都有較詳細(xì)的注釋。
2、本類默認(rèn)模型優(yōu)先,如果沒(méi)有模型就會(huì)查表返回?cái)?shù)據(jù)庫(kù)實(shí)例。
3、還有一點(diǎn)要注意就是你的替換關(guān)鍵詞盡量要跟模版里的字符串不要重復(fù),比如說(shuō),你的替換關(guān)鍵詞叫 ‘id' => catename,而模版里 li id=”xixixi”>a href=”###”>哎呀?/a>/li>,要是這樣就壞了…
求高手改成php原生的,可聯(lián)系qq發(fā)給我嗎?嘿嘿…
具體哪有不清楚的可以聯(lián)系我QQ
效果圖:(好像也支持無(wú)限極菜單)
?php
/**
* Created by PhpStorm.
* User: Chao Chao
* Date: 2017/9/23
* Time: 10:18
* versions: 1.0.0
* url: null
* email: 2776332953@qq.com
* phone: ***
*/
namespace app\index\controller;
use think\Db; // 引用 Db (數(shù)據(jù)庫(kù)鏈接) 類
use think\Url; // 引用 Url ( 創(chuàng)建 url) 類
use think\Loader; // 引用 Loader ( 加載 ) 類
class FrontNav {
// 數(shù)據(jù)庫(kù)實(shí)例
protected $db;
// 無(wú)限極字段名稱
protected $pidName = '';
// 排序設(shè)置
protected $sort = array();
// 一級(jí)導(dǎo)航html模版
protected $levelOne = array();
// 二級(jí)導(dǎo)航html模版
protected $levelTwo = array();
// n級(jí)導(dǎo)航html模版
protected $levelN = array();
// nav html
protected $navHtml = '';
// 替換關(guān)鍵詞
protected $replaceKeywords = array();
/**
* FrontNav constructor. 構(gòu)造方法用于生成數(shù)據(jù)實(shí)例與配置參數(shù)
* @param string $name 數(shù)據(jù)表名稱或模型名稱
* @param string $modelPath 模型所在路徑,默認(rèn)為 admin/model (admin模塊下的model目錄)
* @param string $pidName 無(wú)限極分類的字段(如:pid 或 parentid 等)
* @param string $sort 要排序的字段名稱
* @param array $replaceKeywords 定義的替換關(guān)鍵詞
*/
public function __construct($name, $modelPath, $pidName, $sort, $replaceKeywords) {
// $name 為必填參數(shù)
if (empty($name) || !is_string($name)) {
throw new \think\Exception('參數(shù)錯(cuò)誤 $name(表名稱或模型名稱),實(shí)例化時(shí)該參數(shù)必須為字符串類型且不能為空!');
}
// 模型優(yōu)先考慮 如果 模型類先存在 就返回 模型實(shí)例,否則返回 Db 類實(shí)例。
// 防止大小寫錯(cuò)誤,先都轉(zhuǎn)換成小寫在將第一個(gè)字母大寫 如:Category,因?yàn)?linux 區(qū)分大小寫
$fileName = ucwords(strtolower($name));
// 一般欄目的模型都在后臺(tái),所以這里就寫死了地址 '/admin/model/',也可以傳參制定位置
$modelPath = !empty($modelPath) ? strtolower($modelPath) : 'admin/model';
if (class_exists('app\\' . str_replace('/', '\\', $modelPath) . '\\' . $fileName)) {
$this->db = Loader::model($fileName, 'model', false, 'admin');
} else {
// 不確定在 linux 下數(shù)據(jù)庫(kù)名稱是否區(qū)分大小寫,所以都轉(zhuǎn)換成小寫。
$this->db = Db::name(strtolower($fileName));
}
// 無(wú)限極父類字段不能為空
if (!empty($pidName)) {
$this->pidName = $pidName;
} else {
throw new \think\Exception('參數(shù)錯(cuò)誤 $pidName(父欄目id),實(shí)例化時(shí)字段名稱不能為空!');
}
// 替換關(guān)鍵詞
if (empty($replaceKeywords) || !is_array($replaceKeywords)) {
throw new \think\Exception('參數(shù)錯(cuò)誤 $replaceKeywords(替換關(guān)鍵詞),實(shí)例化時(shí)該參數(shù)必須是而為數(shù)組類型且不能為空!');;
} else {
$this->replaceKeywords = $replaceKeywords;
}
$this->sort = $sort;
}
/**
* 控制器調(diào)用,生成導(dǎo)航菜單。頂層導(dǎo)航的樣式( 參數(shù)2 $levelOneTemplate )為必填項(xiàng),也就是說(shuō)最基本的是一層導(dǎo)航,二級(jí)和多級(jí)是選填項(xiàng)( 參數(shù)3: $levelTwoTemplate 與 參數(shù)4 $levelNTemplate 非必填項(xiàng) )
* @param string $homePageHml 首頁(yè) 標(biāo)簽的html樣式,如: li>a class="navi_home" href="/" rel="external nofollow" rel="external nofollow" >首頁(yè)/a>/li>
* @param array $levelOneTemplate 必填 頂部導(dǎo)航的html樣式,如: array(
* 'ul id="jsddm" class="topNav">', 最外層 ul
* 'li>a href="linkUrl" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" title="catDesc">catName/a>', li標(biāo)簽
* '/li>', li 結(jié)束
* '/ul>' ul 結(jié)束
* )
* @param array $levelTwoTemplate 選填 二級(jí)菜單的html樣式,如: array(
* 'ul class="twoLevel">', 二級(jí)菜單的 ul
* 'li>a href="linkUrl" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" title="catDesc">catName/a>', li標(biāo)簽
* '/li>',li 結(jié)束
* '/ul>'ul 結(jié)束
* )
* @param array $levelNTemplate 選填 多級(jí)菜單的html樣式,如: array(
* 'ul class="nLevel">', N級(jí)菜單的 ul
* 'li>a href="linkUrl" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" title="catDesc">catName/a>', li標(biāo)簽
* '/li>',li 結(jié)束
* '/ul>'ul 結(jié)束
* @return string
*/
public function createNavHtml($homePageHml, $levelOneTemplate, $levelTwoTemplate, $levelNTemplate) {
// 第一層導(dǎo)航不能為空且必須是數(shù)組
if (empty($levelOneTemplate) || !is_array($levelOneTemplate)) {
throw new \think\Exception('參數(shù)錯(cuò)誤 $levelOneTemplate(一級(jí)導(dǎo)航模版),該參數(shù)必須是數(shù)組類型且不能為空!');
}
$this->levelOne = $levelOneTemplate;
// 二級(jí)導(dǎo)航
if (!empty($levelTwoTemplate) !is_array($levelTwoTemplate)) {
throw new \think\Exception('參數(shù)錯(cuò)誤 $levelTwoTemplate(二級(jí)導(dǎo)航模版),該參數(shù)可以為空 \'' 或 array(),否則必須是數(shù)組類型!');
}
$this->levelTwo = $levelTwoTemplate;
// N級(jí)導(dǎo)航
if (!empty($levelNTemplate) !is_array($levelNTemplate)) {
throw new \think\Exception('參數(shù)錯(cuò)誤 $levelNTemplate(N級(jí)導(dǎo)航模版),該參數(shù)可以為空 \'' 或 array(),否則必須是數(shù)組類型!');
}
$this->levelN = $levelNTemplate;
$treeData = $this->getTreeData($this->getAllData(), 0);
//print_r($treeData);
$this->createHtml($treeData);
return $this->levelOne[0] . (!empty($homePageHml) ? $homePageHml : '') . $this->navHtml .
$this->levelOne[3] . "\n";
}
/**
* 獲取所有數(shù)據(jù)
* @return array
*/
private function getAllData() {
if (empty($this->sort) || empty($this->sort['sortField']) || empty($this->sort['sortOrder'])) {
return collection($this->db->where(1)
->select())->toArray();
} else {
return collection($this->db->where(1)
->order($this->sort['sortField'] . ' ' . $this->sort['sortOrder'])
->select())->toArray();
}
}
/**
* 將所有數(shù)據(jù)攢成樹狀結(jié)構(gòu)的數(shù)組
* 增加 levels (層級(jí)) children (子數(shù)組)
* @param $allData 傳遞過(guò)來(lái)的所有非樹狀結(jié)構(gòu)的數(shù)組
* @param $parentId 初始化時(shí)的父欄目id
* @return array 樹狀結(jié)構(gòu)的數(shù)組
*/
private function getTreeData($allData, $parentId) {
$tree = array();
// 層級(jí)計(jì)數(shù)
static $number = 1;
foreach ($allData as $v) {
if ($v[$this->pidName] == $parentId) {
if ($v[$this->pidName] == 0) {
$v['levels'] = 0;
} else {
$v['levels'] = $number;
++$number;
}
$v['children'] = $this->getTreeData($allData, $v['id']);
$tree[] = $v;
} else {
$number = 1;
}
}
return $tree;
}
/**
* 遞歸生成樹狀結(jié)構(gòu)的html
* @param $allData array 由 createNavHtml() 方法傳遞過(guò)來(lái)的 樹形結(jié)構(gòu) 數(shù)據(jù)(數(shù)組)
* @return string 返回(最外層ul內(nèi)部的html)樹狀結(jié)構(gòu)的html
*/
private function createHtml($allData) {
foreach ($allData as $v) {
// 頂部導(dǎo)航
if ($v['levels'] == 0) {
$tempStr0 = $this->levelOne[1];
foreach ($this->replaceKeywords[0] as $k1 => $v1) {
if ($k1 == 'linkUrl') {
$tempStr0 = str_replace($k1, Url::build($v1, 'id=' . $v['id']), "\n" . $tempStr0);
} else {
$tempStr0 = str_replace($k1, $v[$v1], $tempStr0);
}
}
$this->navHtml .= $tempStr0;
if (empty($v['children'])) {
$this->navHtml .= $this->levelOne[2] . "\n";
} else if (!empty($v['children']) !empty($this->levelTwo)) {
$this->navHtml .= "\n" . $this->levelTwo[0] . "\n";
$this->createHtml($v['children']);
$this->navHtml .= $this->levelTwo[3] . $this->levelOne[2];
}
}
// 二級(jí)菜單
if ($v['levels'] == 1) {
$tempStr2 = $this->levelTwo[1];
foreach ($this->replaceKeywords[1] as $k1 => $v1) {
if ($k1 == 'linkUrl') {
$tempStr2 = str_replace($k1, Url::build($v1, 'id=' . $v['id']), $tempStr2);
} else {
$tempStr2 = str_replace($k1, $v[$v1], $tempStr2);
}
}
$this->navHtml .= $tempStr2;
if (empty($v['children'])) {
$this->navHtml .= $this->levelTwo[2] . "\n";
} else if (!empty($v['children']) !empty($this->levelN)) {
// 是否多級(jí)導(dǎo)航,有 children ,還必須有3級(jí) html 模版
$this->navHtml .= "\n" . $this->levelN[0] . "\n";
$this->createHtml($v['children']);
$this->navHtml .= $this->levelN[3] . $this->levelTwo[2] . "\n";
}
}
// 多級(jí)菜單
if (!empty($this->levelN) $v['levels'] > 1) {
$tempStrN = $this->levelN[1];
foreach ($this->replaceKeywords[2] as $k1 => $v1) {
if ($k1 == 'linkUrl') {
$tempStrN = str_replace($k1, Url::build($v1, 'id=' . $v['id']), $tempStrN);
} else {
$tempStrN = str_replace($k1, $v[$v1], $tempStrN);
}
}
$this->navHtml .= $tempStrN;
if (empty($v['children'])) {
$this->navHtml .= $this->levelN[2] . "\n";
} else {
$this->navHtml .= $this->levelN[0];
$this->createHtml($v['children']);
$this->navHtml .= $this->levelN[3] . $this->levelN[2];
}
}
}
return $this->navHtml;
}
}
更多關(guān)于thinkPHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《ThinkPHP入門教程》、《thinkPHP模板操作技巧總結(jié)》、《ThinkPHP常用方法總結(jié)》、《codeigniter入門教程》、《CI(CodeIgniter)框架進(jìn)階教程》、《Zend FrameWork框架入門教程》及《PHP模板技術(shù)總結(jié)》。
希望本文所述對(duì)大家基于ThinkPHP框架的PHP程序設(shè)計(jì)有所幫助。
您可能感興趣的文章:- thinkphp實(shí)現(xiàn)面包屑導(dǎo)航(當(dāng)前位置)例子分享
- ThinkPHP+EasyUI之ComboTree中的會(huì)計(jì)科目樹形菜單實(shí)現(xiàn)方法
- thinkPHP實(shí)現(xiàn)的聯(lián)動(dòng)菜單功能詳解
- thinkPHP基于ajax實(shí)現(xiàn)的菜單與分頁(yè)示例
- ThinkPHP使用心得分享-ThinkPHP + Ajax 實(shí)現(xiàn)2級(jí)聯(lián)動(dòng)下拉菜單
- ThinkPHP無(wú)限級(jí)分類原理實(shí)現(xiàn)留言與回復(fù)功能實(shí)例
- thinkphp實(shí)現(xiàn)無(wú)限分類(使用遞歸)
- ThinkPHP自動(dòng)填充實(shí)現(xiàn)無(wú)限級(jí)分類的方法
- ThinkPHP實(shí)現(xiàn)遞歸無(wú)級(jí)分類——代碼少
- 使用ThinkPHP的自動(dòng)完成實(shí)現(xiàn)無(wú)限級(jí)分類實(shí)例詳解