Skip to content

Commit 3195445

Browse files
committed
Initial import of project, including new helper function for removing
everything before the primary FROM in the SQL query
0 parents  commit 3195445

File tree

2 files changed

+323
-0
lines changed

2 files changed

+323
-0
lines changed

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# PHP Pagination Class
2+
3+
Based off my original "Making Pagination Easier" blog post (http://www.michaelpeacock.co.uk/blog/entry/making-pagination-easier-with-php-class), however it has been altered to adjust the query so that the total count can be calculated by querying for a single row with a count included.
4+
5+
## Usage
6+
7+
<?php
8+
require_once('pagination.class.php');
9+
// establish a database connection in your code
10+
$db = mysqli_connect( 'localhost', 'root', '', 'database');
11+
// create the pagination object, and pass the database connection
12+
$p = new Pagination( $db );
13+
// set a limit
14+
$p->setLimit(3);
15+
// set an offset
16+
$p->setOffset( isset( $_GET['page_number'] ) ? intval( $_GET['page_number'] ) : 0 );
17+
// set the query
18+
$p->setQuery( "SELECT * FROM something " );
19+
// do the pagination
20+
$p->generatePagination();
21+
// what we do with these variables depends on the tempLating system used: the pagination object could send them direct to the template system for us
22+
// get an array of results
23+
$results = $p->getResults();
24+
// get the current page number
25+
$current_page = $p->getCurrentPage();
26+
// get the number of pages
27+
$number_of_pages = $p->getNumPages();
28+
29+
$first_page_link = $p->isFirst() ? "" : "<a href='?page_number=0'>First page</a>";
30+
$previous_page_link = $p->isFirst() ? "" : "<a href='?page_number=".( $p->getCurrentPage() - 2 )."'>Previous page</a>";
31+
32+
$next_page_link = $p->isLast() ? "" : "<a href='?page_number=" . $p->getCurrentPage() . "'>Next page</a>";
33+
$last_page_link = $p->isLast() ? "" : "<a href='?page_number=".( $p->getCurrentPage() - 1 )."'>Last page</a>";
34+
35+
36+
echo '<ul>';
37+
foreach( $results as $result )
38+
{
39+
echo '<li>' . $result['something'] . '</li>';
40+
}
41+
echo '</ul>';
42+
echo 'Page ' . $current_page . ' of ' . $number_of_pages . '<br />';
43+
echo $first_page_link . ' ' . $previous_page_link . ' ' . $next_page_link . ' ' . $last_page_link;
44+
?>

pagination.class.php

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
<?php
2+
/**
3+
* Pagination class
4+
* Making pagination of records easy(ier)
5+
* @author Michael Peacock
6+
* @url www.michaelpeacock.co.uk
7+
*/
8+
class Pagination {
9+
10+
/**
11+
* MySQLi Connection
12+
*/
13+
private $db;
14+
15+
/**
16+
* The query we will be paginating
17+
*/
18+
private $query = "";
19+
20+
/**
21+
* The processed query which will be executed
22+
*/
23+
private $executedQuery = "";
24+
25+
/**
26+
* The results from the query
27+
*/
28+
private $results;
29+
30+
/**
31+
* The maximum number of results to display per page
32+
*/
33+
private $limit = 25;
34+
35+
/**
36+
* The results offset - i.e. page we are on (-1)
37+
*/
38+
private $offset = 0;
39+
40+
/**
41+
* The number of rows there were in the query passed
42+
*/
43+
private $numRows;
44+
45+
/**
46+
* The number of rows on the current page (main use if on last page, may not have as many as limit on the page)
47+
*/
48+
private $numRowsPage;
49+
50+
/**
51+
* Number of pages of results there are
52+
*/
53+
private $numPages;
54+
55+
/**
56+
* Is this the first page of results?
57+
*/
58+
private $isFirst;
59+
60+
/**
61+
* Is this the last page of results?
62+
*/
63+
private $isLast;
64+
65+
/**
66+
* The current page we are on
67+
*/
68+
private $currentPage;
69+
70+
/**
71+
* Our constructor
72+
* @param mysqli $mysqli_link
73+
* @return void
74+
*/
75+
function __construct( $mysqli_link )
76+
{
77+
$this->db = $mysqli_link;
78+
}
79+
80+
/**
81+
* Process the query, and set the paginated properties
82+
* @return bool (true if there are some rows on the page, false if there are not)
83+
*/
84+
public function generatePagination()
85+
{
86+
$temp_query = $this->query;
87+
88+
// its more efficient to query one row (if possible) and include a count, as opposed to querying all of them
89+
if( preg_match( '#SELECT DISTINCT((.+?)),#si', $temp_query ) > 0 )
90+
{
91+
// this is a distinct query, we really have to query them all :-(
92+
$q = mysqli_query( $this->db, $temp_query );
93+
$nums = mysqli_num_rows( $q );
94+
$this->numRows = $nums;
95+
}
96+
else
97+
{
98+
// normal query, let's strip out everything before the "primary" FROM
99+
$q = mysqli_query( $this->db, "SELECT COUNT(*) AS nums " . $this->excludePrimarySelects( $temp_query ) . " LIMIT 1" );
100+
if( mysqli_num_rows( $q ) == 1 )
101+
{
102+
// how many rows?
103+
$row = mysqli_fetch_array( $q, MYSQLI_ASSOC );
104+
$this->numRows = $row['nums'];
105+
}
106+
else
107+
{
108+
// query didn't work...0 rows
109+
$this->numRows = 0;
110+
}
111+
}
112+
113+
// limit!
114+
$this->executedQuery = $temp_query . " LIMIT " . ( $this->offset * $this->limit ) . ", " . $this->limit;
115+
116+
$q = mysqli_query( $this->db, $this->executedQuery );
117+
while( $row = mysqli_fetch_array( $q, MYSQLI_ASSOC ) )
118+
{
119+
$this->results[] = $row;
120+
}
121+
122+
// be nice...do some calculations
123+
124+
// num pages
125+
$this->numPages = ceil($this->numRows / $this->limit);
126+
// is first
127+
$this->isFirst = ( $this->offset == 0 ) ? true : false;
128+
// is last
129+
$this->isLast = ( ( $this->offset + 1 ) == $this->numPages ) ? true : false;
130+
// current page
131+
$this->currentPage = ( $this->numPages == 0 ) ? 0 : $this->offset +1;
132+
$this->numRowsPage = mysqli_num_rows( $q );
133+
134+
return ( $this->numRowsPage == 0 ) ? false : true;
135+
136+
}
137+
138+
//===========================================================================//
139+
// HELPER METHODS //
140+
//===========================================================================//
141+
142+
/**
143+
* Exclude the primary selects from the SQL query
144+
* @param String $sql the SQL query
145+
* @return String the query starting with FROM
146+
*/
147+
private function excludePrimarySelects( $sql )
148+
{
149+
$word = "from";
150+
$wordLength = strlen( $word );
151+
$left = 0;
152+
$right = 0;
153+
$within = 0;
154+
$precedingSQLStatement = "";
155+
for( $i = 0; $i < ( strlen( $sql ) ); $i++ )
156+
{
157+
$left = ( $sql[ $i ] == "(" ) ? $left+1 : $left;
158+
$right = ( $sql[ $i ] == ")" ) ? $right+1 : $right;
159+
if( $left === $right )
160+
{
161+
if( $within < $wordLength && strcasecmp( $sql[ $i ], $word[ $within ] ) == 0 )
162+
{
163+
$within++;
164+
}
165+
elseif( $within <> $wordLength )
166+
{
167+
$within = 0;
168+
}
169+
}
170+
elseif( $within <> $wordLength )
171+
{
172+
$within = 0;
173+
}
174+
175+
if( $within < $wordLength )
176+
{
177+
$precedingSQLStatement .= $sql[ $i ];
178+
}
179+
elseif( $within == $wordLength )
180+
{
181+
$precedingSQLStatement .= $sql[ $i ];
182+
break;
183+
}
184+
}
185+
186+
return str_replace( $precedingSQLStatement, " FROM ", $sql );
187+
}
188+
189+
190+
//===========================================================================//
191+
// GETTER AND SETTER METHODS //
192+
//===========================================================================//
193+
194+
/**
195+
* Set the query to be paginated
196+
* @param String $sql the query
197+
* @return void
198+
*/
199+
public function setQuery( $sql )
200+
{
201+
$this->query = $sql;
202+
}
203+
204+
/**
205+
* Set the limit of how many results should be displayed per page
206+
* @param int $limit the limit
207+
* @return void
208+
*/
209+
public function setLimit( $limit )
210+
{
211+
$this->limit = $limit;
212+
}
213+
214+
/**
215+
* Set the offset - i.e. if offset is 1, then we show the next page of results
216+
* @param int $offset the offset
217+
* @return void
218+
*/
219+
public function setOffset( $offset )
220+
{
221+
$this->offset = $offset;
222+
}
223+
224+
/**
225+
* Get the result set
226+
* @return array
227+
*/
228+
public function getResults()
229+
{
230+
return $this->results;
231+
}
232+
233+
/**
234+
* Get the number of pages of results there are
235+
* @return int
236+
*/
237+
public function getNumPages()
238+
{
239+
return $this->numPages;
240+
}
241+
242+
/**
243+
* Is this page the first page of results?
244+
* @return bool
245+
*/
246+
public function isFirst()
247+
{
248+
return $this->isFirst;
249+
}
250+
251+
/**
252+
* Is this page the last page of results?
253+
* @return bool
254+
*/
255+
public function isLast()
256+
{
257+
return $this->isLast;
258+
}
259+
260+
/**
261+
* Get the current page within the paginated results we are viewing
262+
* @return int
263+
*/
264+
public function getCurrentPage()
265+
{
266+
return $this->currentPage;
267+
}
268+
269+
/**
270+
* Get the number of rows there are on the current page
271+
* @return int
272+
*/
273+
public function getNumRowsPage()
274+
{
275+
return $this->numRowsPage;
276+
}
277+
278+
}
279+
?>

0 commit comments

Comments
 (0)