分頁是一個網站的常見功能, 所以勢必要學會如何使用! 那我們開始吧!
首先是Controller的部分:
說明:
function actionIndex(){ $criteria = new CDbCriteria(); $count=Article::model()->count($criteria); $pages=new CPagination($count); $pages->pageSize=10; $pages->applyLimit($criteria); $models = Post::model()->findAll($criteria); $this->render('index', array( 'models' => $models, 'pages' => $pages )); }
1. CDbCriteria把你要抓的資料條件都設好 ( 查詢資料大解密之"CDbCriteria到底是什麼? )
2. count得到符合條件的資料筆數
3. 把得到的資料筆數丟到CPagination裡
4. pageSize設定每個分頁要顯示幾筆
6. 將$pages渲染 (render)到view去
再來是View的部分:
<?php foreach($models as $model): ?> // 顯示一個模型 <?php endforeach; ?> // 顯示分頁 <?php $this->widget('CLinkPager', array( 'pages' => $pages, )) ?>
1. 輸出你的資料
2. 使用小工具widget的CLinkPager來顯示分頁按鈕 (超屌的) ( 官方的CLinkPager說明 )
以我目前的需求, 配置如下:
$this->widget('CLinkPager', array(
'header' => '',
'prevPageLabel' => '上一頁',
'nextPageLabel' => '下一頁',
'pages' => $pages,
'maxButtonCount' => 10
));
1. header -> 在分頁按鈕上多行文字說明
2. prevPageLabel 跟 nextPageLabel -> 不用多說了吧!
3. pages -> 返回此分頁的分頁訊息
4. maxButtonCount -> 顯示的最多分頁按鈕數
上面內容引用自官方說明 (中文):
接下來才是重點:
講到這, 如果你有google過的話, 你會發現都大同小異吧!因為網路上幾乎都不講原裡的.
運作原理:
applyLimit的limit跟offset, 其實指的是每個分頁的資料數跟移到開始抓資料的基準點 (大陸翻譯偏移量, 鬼看的懂阿!可能我資質不好吧~)
ex:
總資料數有32筆, 我們的pageSize設為5, 那就會有7個分頁.
然後當我們按第三個分頁的時候 (ex: index.php?r=food/list&page=3), 程式就會將位置 (基準點)移到第10筆, 然後開始抓5筆, 所以就會得到11~15的資料了!
你也許會想說為什麼位置會移到第10筆呢?問的好, 有好奇心, 答案就在這
public function applyLimit($criteria)
{
$criteria->limit=$this->getLimit();
$criteria->offset=$this->getOffset();
}
我們接著看getLimit()
public function getLimit()
{
return $this->getPageSize();
}
再看看getPageSize()
public function getPageSize()
{
return $this->_pageSize;
}
哦~ 原來就是我們設定的pageSize嘛~ 也就是"5".
ok, good~ 我們再來乘勝追擊, 來查查看getOffset()
public function getOffset()
{
return $this->getCurrentPage()*$this->getPageSize();
}
哦~ 所以是getCurrentPage()乘上5
那getCurrentPage()是什麼呢?
public function getCurrentPage($recalculate=true)
{
if($this->_currentPage===null || $recalculate)
{
if(isset($_GET[$this->pageVar]))
{
$this->_currentPage=(int)$_GET[$this->pageVar]-1;
if($this->validateCurrentPage)
{
$pageCount=$this->getPageCount();
if($this->_currentPage>=$pageCount)
$this->_currentPage=$pageCount-1;
}
if($this->_currentPage<0)
$this->_currentPage=0;
}
else
$this->_currentPage=0;
}
return $this->_currentPage;
}
恩...有點長,
說明一下:
這支程式會GET我們前端傳來的page變數, 我查過發現pageVar預設的就是page這個變數名. 然後getPageCount()的code如下:
public function getPageCount()
{
return (int)(($this->_itemCount+$this->_pageSize-1)/$this->_pageSize);
}
itemCount就是我們new CPagination($count)的$count值, 依我們的舉例就是32.
(32+5-1)/5 = 7.2 也就符合我們前面說的7個分頁.
如果page傳來的是7那_currentPage就是6, 6沒有大於7.2也沒有小於0, 所以getCurrentPage就直接返回6.
在回到getOffset(), 6*5=30, 所以就會從30開始抓5筆, 由於我們總資料只有32筆, 所以第7個分頁只會有2筆資料顯示.
把yii的code翻了個底朝天才終於搞清楚來龍去脈, 呼~ 真是各種折騰啊T.T, 不過完全搞清楚的感覺真的好爽, 哈哈哈哈.
最後:
我當時試半天搞不定的原因是, 當我按下分頁的時候, 當初的搜尋條件沒有跟著帶過去, 所以抓不到資料、出錯! 最後我是用Cookie將那些條件存起來, 要用的時候再拿出來, 這樣就解決嘍!
不過記得, 如果是重要的資料千萬不要存到Cookie裡喔^^
不過yii真的好厲害, 把分頁這樣的東西封裝成這麼好操作的物件, 真的很屌^^
好東西:
這個是國外大大寫的線上範例 (可操作, 會更好理解!)
http://www.yiiplayground.com/index.php?r=UiModule/pagination/basicPager
沒有留言:
張貼留言