1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\data;
use Yii;
use yii\base\Object;
/**
* Pagination represents information relevant to pagination of data items.
*
* When data needs to be rendered in multiple pages, Pagination can be used to
* represent information such as [[totalCount|total item count]], [[pageSize|page size]],
* [[page|current page]], etc. These information can be passed to [[yii\widgets\Pager|pagers]]
* to render pagination buttons or links.
*
* The following example shows how to create a pagination object and feed it
* to a pager.
*
* Controller action:
*
* ~~~
* function actionIndex()
* {
* $query = Article::find()->where(array('status' => 1));
* $countQuery = clone $query;
* $pages = new Pagination(array('totalCount' => $countQuery->count()));
* $models = $query->offset($pages->offset)
* ->limit($pages->limit)
* ->all();
*
* return $this->render('index', array(
* 'models' => $models,
* 'pages' => $pages,
* ));
* }
* ~~~
*
* View:
*
* ~~~
* foreach ($models as $model) {
* // display $model here
* }
*
* // display pagination
* echo LinkPager::widget(array(
* 'pagination' => $pages,
* ));
* ~~~
*
* @property integer $pageCount Number of pages.
* @property integer $page The zero-based index of the current page.
* @property integer $offset The offset of the data. This may be used to set the
* OFFSET value for a SQL statement for fetching the current page of data.
* @property integer $limit The limit of the data. This may be used to set the
* LIMIT value for a SQL statement for fetching the current page of data.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Pagination extends Object
{
/**
* @var string name of the parameter storing the current page index. Defaults to 'page'.
* @see params
*/
public $pageVar = 'page';
/**
* @var boolean whether to always have the page parameter in the URL created by [[createUrl()]].
* If false and [[page]] is 0, the page parameter will not be put in the URL.
*/
public $forcePageVar = true;
/**
* @var string the route of the controller action for displaying the paged contents.
* If not set, it means using the currently requested route.
*/
public $route;
/**
* @var array parameters (name => value) that should be used to obtain the current page number
* and to create new pagination URLs. If not set, $_GET will be used instead.
*
* The array element indexed by [[pageVar]] is considered to be the current page number.
* If the element does not exist, the current page number is considered 0.
*/
public $params;
/**
* @var boolean whether to check if [[page]] is within valid range.
* When this property is true, the value of [[page]] will always be between 0 and ([[pageCount]]-1).
* Because [[pageCount]] relies on the correct value of [[totalCount]] which may not be available
* in some cases (e.g. MongoDB), you may want to set this property to be false to disable the page
* number validation. By doing so, [[page]] will return the value indexed by [[pageVar]] in [[params]].
*/
public $validatePage = true;
/**
* @var integer number of items on each page. Defaults to 10.
* If it is less than 1, it means the page size is infinite, and thus a single page contains all items.
*/
public $pageSize = 10;
/**
* @var integer total number of items.
*/
public $totalCount = 0;
/**
* @return integer number of pages
*/
public function getPageCount()
{
if ($this->pageSize < 1) {
return $this->totalCount > 0 ? 1 : 0;
} else {
$totalCount = $this->totalCount < 0 ? 0 : (int)$this->totalCount;
return (int)(($totalCount + $this->pageSize - 1) / $this->pageSize);
}
}
private $_page;
/**
* Returns the zero-based current page number.
* @param boolean $recalculate whether to recalculate the current page based on the page size and item count.
* @return integer the zero-based current page number.
*/
public function getPage($recalculate = false)
{
if ($this->_page === null || $recalculate) {
$params = $this->params === null ? $_GET : $this->params;
if (isset($params[$this->pageVar]) && is_scalar($params[$this->pageVar])) {
$this->_page = (int)$params[$this->pageVar] - 1;
if ($this->validatePage) {
$pageCount = $this->getPageCount();
if ($this->_page >= $pageCount) {
$this->_page = $pageCount - 1;
}
}
if ($this->_page < 0) {
$this->_page = 0;
}
} else {
$this->_page = 0;
}
}
return $this->_page;
}
/**
* Sets the current page number.
* @param integer $value the zero-based index of the current page.
*/
public function setPage($value)
{
$this->_page = $value;
}
/**
* Creates the URL suitable for pagination with the specified page number.
* This method is mainly called by pagers when creating URLs used to perform pagination.
* @param integer $page the zero-based page number that the URL should point to.
* @return string the created URL
* @see params
* @see forcePageVar
*/
public function createUrl($page)
{
$params = $this->params === null ? $_GET : $this->params;
if ($page > 0 || $page >= 0 && $this->forcePageVar) {
$params[$this->pageVar] = $page + 1;
} else {
unset($params[$this->pageVar]);
}
$route = $this->route === null ? Yii::$app->controller->route : $this->route;
return Yii::$app->getUrlManager()->createUrl($route, $params);
}
/**
* @return integer the offset of the data. This may be used to set the
* OFFSET value for a SQL statement for fetching the current page of data.
*/
public function getOffset()
{
return $this->pageSize < 1 ? 0 : $this->getPage() * $this->pageSize;
}
/**
* @return integer the limit of the data. This may be used to set the
* LIMIT value for a SQL statement for fetching the current page of data.
* Note that if the page size is infinite, a value -1 will be returned.
*/
public function getLimit()
{
return $this->pageSize < 1 ? -1 : $this->pageSize;
}
}