I have a SQL query that separates the results into groups of 25:
$page = 0; // 1, 2, 3
$perPage = 25;
....
ORDER BY c.date DESC LIMIT " . ( $page * $perPage ) . ", " . $perPage);
I'm trying to figure out how I write something that loops through the number of $page returned and then echos a number back to the screen. Ie. Page 1, Page2, Page3 - based on $page.
I will assume the search PHP page is driven throught GET parameters like page like a.php?page=5 or something.
In that case, try something of this sort:
$total = //total no. of rows. if using mysql use: mysql_numrows($resource);
$total = ceil($total/$perPage);
for ($i=0; $i<$total; $i++){
echo 'Page ' . ($i+1) . '';
}
This is just to give you a kick start. You can obviously, take this ahead in the way you would like.
What you are doing is called Pagination. Just google for PHP Pagination, and you will end up with lots of results. And most of them are just too easy to use.
Try Zend Paginator: http://framework.zend.com/manual/en/zend.paginator.html
Related
I have a variable $h, which counts the number of properties in my foreach. I then have a number stored in $nb_elem_per_page to limit the number of properties shown per page.
<?php $sum_total = ceil($h / $nb_elem_per_page); ?>
I then use the above to work out how many pages these will need. For example $nb_elem_per_page is currently 12. So if $h was 123 it would need 11 pages.
Is there a way for me, using the number from $sum_total create links for the number here, such as:
http://www.website.co.uk/properties/search/?bed=4&go=1
http://www.website.co.uk/properties/search/?bed=4&go=2
http://www.website.co.uk/properties/search/?bed=4&go=3
So it outputs the number of links based on the number in $sum_total, but on each one the end number goes up 1 each time as above? This would then be my pagination.
for ($i = 1; $i < $sum_total; $i++) {
echo "{$i}";
}
Or whatever you would like.
You can refer to php's documentation here : http://php.net/manual/en/control-structures.for.php
I have a news table in MySQL Database I query the table and show the title of the news in one PHP pages but now the table getting bigger so I want to divide the results into pages I mean to show each 50 news title in one page (pagenation).
I use this query to bring the news :
SELECT news.*, categories.category, users.username
FROM news INNER JOIN
users on news.user_id = users.id INNER JOIN
categories on categories.id = news.category_id
order by news.timestamp DESC
limit $min,$max
and this is part of the PHP page (How I calculate the max and min)
$news_per_page = 50;
if(!empty($_GET['p_n']))
{
$p_n = $_GET['p_n'];
$max = $news_per_page*$p_n;
$min = ($max - $news_per_page);
}
else
{
$p_n = 1;
$max = 50;
$min = 0;
}
$news = all_news($max,$min);
The sql giving me wrong result when i pass the limits I do not know why. Is it wrong to specify the max and min of sql query by this way?? Should I correct something in this code?
The LIMIT clause, as explained in the docs, takes arguments offset and count. So if you want to get, for example, results from 201 to 250, you would use LIMIT 200, 50. Start by renaming your variables $min and $max to $offset and $count, and from there everything will fall into place.
Pseudocode:
offset = (requestedPageNumber - 1) * rowsPerPage;
count = rowsPerPage;
PHP Code:
(assuming page number is 0-based)
$rowsPerPage = 50;
$page = empty($_GET['p_n']) ? 0 : $_GET['p_n'];
$offset = $rowsPerPage * (int) $page;
$news = all_news($offset, $rowsPerPage);
If you've got problems handling pagination properly, I suggest you use some code that is working, for example a pagination class that takes three parameters:
The current page.
The total count.
The number of items per page.
And then that class will generate the LIMIT clause for you. Example:
$pageNumber = 1;
$totalCount = 17;
$perPage = 5;
$pagination = new LimitPagination($pageNumber, $totalCount, $perPage);
echo $pagination, "\n";
This would output
LIMIT 0, 5
because you'er on the first page. Such a class then could also filter out those problems you have here, for example setting to a negative page - just automatically. And also it can provide a lot of extra data, like the next and previous page, the current page, the number of total pages, if it is the first or the last page and what not:
$pagination->setPage(-2);
echo $pagination, "\n";
echo "Current: ", $pagination->getPage(),
"; Total: ", $pagination->getTotalPages(),
"; Previous: ", $pagination->getPreviousPage(),
"; Next: ", $pagination->getNextPage(),
"\n";
Output:
LIMIT 0, 5
Current: 1; Total: 4; Previous: 1; Next: 2
This is then easy to integrate with different code, including yours:
$pagination = new LimitPagination($_GET['p_n'], $totalCount, 50);
$limit = sprintf("%d, %d", $pagination->getOffset(), $pagination->getCount());
This should easily do it. Class is here as Gist: https://gist.github.com/4469154
You need to set start (this you can achieve by using current page and per page property) and the second information is how many results you want (again per page property).
LIMIT . ($p_n - 1) * $news_per_page .', ' . $news_per_page
So, in your script it will be:
if(!empty($_GET['p_n']))
{
// You need to protect your variables for SQL injection. For numbers (int) or integer() function it is enough.
$p_n = (int) $_GET['p_n'];
$max = (int) $news_per_page;
$min = (int) ($p_n - 1) * $news_per_page;
}
else
{
$p_n = 1;
$max = 50;
$min = 0;
}
The correct code is:
$news_per_page = 50;
if(!empty($_GET['p_n']))
{
$p_n = intval($_GET['p_n']);
$min = ($p_n-1) * $news_per_page;
$max = $news_per_page;
}
else
{
$p_n = 1;
$max = 50;
$min = 0;
}
$news = all_news($max,$min);
While $_GET['p_n'] is page_number you dont' need to make any multiplies
I whipped up some code to count the number of rows from my database, and through a little script, display "Page : 1 2 3 4 5" etc.
Here is my code:
$totalRows = mysql_num_rows
$rpp = 20
$totalPages = ceil($totalRows/$rpp);
$i;
for (i=0; i<totalPages; i++){
echo "Page: " . "<a href='index.php?page=\"$i\"rpp=20>\"$i\"</a>";
}
Does this look good? Do I need anything else?
EDIT 1: Added ceil() to round up. No more missing results :-)!
I think you need to round $totalPages to the next highest integer, ie.
$totalPages = ceil($totalRows/$rpp);
Ok so iv got this code which is suppose to bring back all my results from my database and display 5 results per page. At the moment I have 12 results in my database and it is only showing 10, it wont show the 3rd page as there isnt 5 results to display. Here is my code
//$_GET['page'] is to get the current page opened
if (isset($_GET["page"])) { $page = $_GET["page"]; } else { $page=1; };
$results_per_page = "5"; //number of results I want displayed per page
$start_from = ($page-1) * $results_per_page;
$query = "SELECT * FROM items WHERE subcat = '$conditions' LIMIT $start_from, $results_per_page";
$result = mysql_query($query) or die("Unable to verify user because : " . mysql_error());
while ($row_condition=mysql_fetch_array($result)) {
//Display the results here
}
//Count number of results from database and work out how
//many pages I need to display all the results.
$result1 = mysql_query("SELECT * FROM items WHERE subcat = '$conditions'");
$num_rows = mysql_num_rows($result1);
$num_pages = $num_rows / $results_per_page;
if ($num_rows > $results_per_page){
?>
<div id="pagenum">
<?php
//This creates and displays the page numbers for the user to select
foreach( range( 1, $num_pages) as $i) {
if ($thepage == $i){
echo '<b>' . $i . '</b>';
}else{
echo '' . $i . '';
}
//This places a line between each number of pages
if ($i == $num_pages){
}else{
echo " | ";
}
}
?>
</div>
<?php
}else{ echo "Test";}
?>
So can anyone see a problem with this?, so I have 12 entries in my database. However im only getting 2 pages, 5 on each page and im not getting the 3rd page as there are only 2 results left and it seems to want 5 to finish it.
Thanks
You need to use ceil function:
$num_pages = ceil($num_rows / $results_per_page);
I think your biggest problem is that PHP will make give you a float when you divide two numbers that don't result in a whole one.
$one = 12;
$two = 5;
$result = $one / $two; // That will result in 2.4
Now, the issue is you, technically, have three pages, but PHP will NOT treat the .4 pages as a page, so when you loop through it will technically only do it twice. Since your using range and it's 2.4, it seems like PHP is rounding down. I would suggest something like this:
$result1 = mysql_query("SELECT * FROM items WHERE subcat = '$conditions'");
$num_rows = mysql_num_rows($result1);
$num_pages = ceil($num_rows / $results_per_page);
if ($num_rows > $results_per_page){
for($i = 0; $i < $num_pages; $i++) {
ceil() will force that division to round up every time, which will always give you that extra page.
Give it a shot! Let me know if it fixes your issue!
I have a search result from MySQL query or Array or something else. The result gave a variable $totalfiles say for example 25. The number of results is limited to $limit, here 12. The maximum number of pages calculated, $maxpages, will be 3.
As we consider the case, we will get 12 results for pages 1 and 2, and 1 for page 3.
What is the easiest way to predict (or calculate) the number of results in a specific page using variables $totalfiles, $limit, $maxpages and $pagenumber using PHP? I don't think all these 4 variables are necessary for doing this.
The only page that is allowed to have a number that is different from $limit is the last one. Don't forget that. And the last page will always have the remainder of the integer division
$last_page_items = $totafiles % $limit;
If $last_page_items is 0, means that you have all pages with $limit items
also,
$pages = ceil($totalfiles / $limit);
R = Number of rows on a given page, P, where P starts at 1.
T = Total rows
L = Rows per page
R = T - ((P-1) * L)
Then just add a check afterwards to set R to 0 if R < 0.
Code:
function get_num_rows_on_page($page, $total_rows, $per_page) {
$on_page = $total_rows - ( ($page-1) * $per_page );
return $on_page < 0 ? 0 : $on_page;
}
Max pages: Total files, divided by the limit. If the remainder is greater than 0, add one.
$maxpages = $totalfiles/$limit;
if ($totalfiles % $limit > 0) $maxpages++;
Number on current page: if Page number less than Max page, there are limit results. If Page number is the Max page, there are (Remainder of Total Files divided by limit) results if that remainder is greater than 0, otherwise limit.
$results = $limit;
$rem = $totalfiles % limit;
if ($pagenumber == $maxpages && $rem > 0) $results = $rem;
If you want to distribute the results evenly in the maximum number of pages, which is 3 as you have suggested, you can use:
$results_per_page = ($totalfiles/$maxpages);
Otherwise, you already have the number of results per page calculated on your $limit variable.
Try this:
function getPageSize($total, $maxpages, $pagenumber){
$itemsperpage=intval($total/$maxpages);
if($pagenumber == $maxpages){
$itemslastpage=abs($total-($itemsperpage*$maxpages));
return $itemslastpage;
}else{
return $itemsperpage;
}
}
// should print '5'
echo getPageSize(29,6,6) . "\n";
// should print '7'
echo getPageSize(14,2,1) . "\n";
Note that $limit is not needed as it is only used to control results from database.