相信不少使用dedecms的朋友在網上查找關於dede:sql標籤進行分頁的解決方案時都不盡如人意,尤爲是在列表頁使用dede:sql調用外部數據(所謂調用外部數據就是指在後臺只是建立個空欄目,而後對應的列表模板文件中使用dede:sql指定自定義的數據源,數據源與該欄目自己是沒有邏輯關係的,目的是爲了讓織夢能按照它的規則來幫咱們將數據源生成靜態文件予以展現)時,我本人也搜索了不少資料,網上的答案都不夠完美,有的是直接在模板文件中執行php代碼來實現分頁,顯然此方法沒法生成靜態文件,有的直接在sql裏面指定limit參數,但又沒法實現智能分頁,織夢官方也沒有給出具體的解決方案,在dede論壇有看到織夢核心人物天涯給出的回覆是採用自由列表的方法,顯然自由列表沒法指定外部數據源,最後實在沒辦法只能本身動手了,首先想到的思路是將dede:list標籤進行改造了,熟悉dede的朋友應該知道這個列表頁專用標籤的工做原理大體是先經過欄目變量id獲取到對應的數據源再呈現到頁面上來,那麼咱們就可讓它不單單經過欄目變量id還能夠經過指定的sql語句來獲取數據源了,好比咱們能夠另外嵌入一個相似{dede:listsql sql='select * from dede_feedback' pagesize='10'}的標籤來使用。php
OK,思路已經有了,接下來咱們打開include/arc.listview.class.php這個文件來給它修整下吧!sql
找到:數據庫
if(!is_object($ctag)) { $ctag = $this->dtp->GetTag("list"); }
這一段,在其後添加以下代碼:數組
//Add by Rainyin 2012-09-26 if(!is_object($ctag)) { $ctag = $this->dtp->GetTag("listsql"); if (is_object($ctag)) { $cquery = $ctag->GetAtt("sql"); $cquery = preg_replace("/SELECT(.*?)FROM/is", " SELECT count(*) as dd FROM ", $cquery); $cquery = preg_replace("/ORDER(.*?)SC/is", "", $cquery); $row = $this->dsql->GetOne($cquery); if(is_array($row)) { $this->TotalResult = $row['dd']; } else { $this->TotalResult = 0; } } } //End
而後找到:post
if($ctag->GetName()=="list") { $limitstart = ($this->PageNo-1) * $this->PageSize; $row = $this->PageSize; if(trim($ctag->GetInnerText())=="") { $InnerText = GetSysTemplets("list_fulllist.htm"); } else { $InnerText = trim($ctag->GetInnerText()); } $this->dtp->Assign($tagid, $this->GetArcList( $limitstart, $row, $ctag->GetAtt("col"), $ctag->GetAtt("titlelen"), $ctag->GetAtt("infolen"), $ctag->GetAtt("imgwidth"), $ctag->GetAtt("imgheight"), $ctag->GetAtt("listtype"), $ctag->GetAtt("orderby"), $InnerText, $ctag->GetAtt("tablewidth"), $ismake, $ctag->GetAtt("orderway") ) ); }
這一段,在其後添加以下代碼:測試
//Add by Rainyin 2012-09-26 else if($ctag->GetName()=="listsql") { $limitstart = ($this->PageNo-1) * $this->PageSize; $row = $this->PageSize; if(trim($ctag->GetInnerText())=="") { $InnerText = GetSysTemplets("list_fulllist.htm"); } else { $InnerText = trim($ctag->GetInnerText()); } $this->dtp->Assign($tagid, $this->GetSqlList( $limitstart, $row, $ctag->GetAtt("sql"), $InnerText ) ); } //End
最後找到function GetArcList這個方法,在這個方法結束後面添加一個能夠經過傳入sql參數獲取指定數據源的方法this
代碼以下:code
//Add by Rainyin 2012-09-26 function GetSqlList($limitstart = 0, $row = 10, $sql = '', $innertext){ global $cfg_list_son; $innertext = trim($innertext); if ($innertext == '') { $innertext = GetSysTemplets('list_fulllist.htm'); } //處理SQL語句 $limitStr = " LIMIT {$limitstart},{$row}"; $this->dsql->SetQuery($sql . $limitStr); $this->dsql->Execute('al'); $t2 = ExecTime(); //echo $t2-$t1; $sqllist = ''; $this->dtp2->LoadSource($innertext); $GLOBALS['autoindex'] = 0; //獲取字段 while($row = $this->dsql->GetArray("al")) { $GLOBALS['autoindex']++; if(is_array($this->dtp2->CTags)) { foreach($this->dtp2->CTags as $k=>$ctag) { if($ctag->GetName()=='array') { //傳遞整個數組,在runphp模式中有特殊做用 $this->dtp2->Assign($k,$row); } else { if(isset($row[$ctag->GetName()])) { $this->dtp2->Assign($k,$row[$ctag->GetName()]); } else { $this->dtp2->Assign($k,''); } } } } $sqllist .= $this->dtp2->GetResult(); }//while $t3 = ExecTime(); //echo ($t3-$t2); $this->dsql->FreeResult('al'); return $sqllist; } //End
總共就添加三段代碼,每一段代碼基本都參考它緊接着的上面那段原始代碼,而無需改變它原來任何一個地方的代碼,應該算是比較完美的手術了,接下來在模板文件中的使用方法就跟一開始思路中所提到的那樣,分頁標籤依舊沿用原來的htm
調用範例:it
// //{dede:listsql sql='select id,post_title from dede_feedback' pagesize='10'} // // [field:username /][field:dtime function="MyDate('Y-m-d',@me)"/] // [field:msg /] // //{/dede:listsql} // //{dede:pagelist listsize='2' listitem='index pre pageno next end '/} //
注:通過本人測試,以上解決方案適用於dedecms5.6和最新的dedecms v5.7版本。
支持跨數據庫調用,例:
// //// // // {dede:listsql sql='select * from ecshop.ecs_comment order by add_time desc' pagesize='10'} // [field:user_name/]:[field:title/] // [field:content/]... // [field:add_time function="MyDate('Y-m-d',@me)"/] // // {/dede:listsql} // // // // {dede:pagelist listitem="info,index,end,pre,next,pageno" listsize="2"/} // // //