Code not working, Sorting MySQL results into pages - php

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!

Related

how to Limit pagination pages links?

I have my pagination page links like this.And the pagegrows like:
1 2 3 4 5 6 7 ,8,9,10 and goes on.
But i want to limit this so if there is more than 5 pages it shall only show 5 links like this:
1 2 3 4 5... 97 98 99
where 99 is the last page.
And if you go to next page it will only change the first pages like this:
3 4 5 ... 97 98 99
function pagination($current_page_number, $total_records_found, $query_string = null)
{
$page = 1;
echo "Page: ";
for ($total_pages = ($total_records_found/NUMBER_PER_PAGE); $total_pages > 0; $total_pages--)
{
if ($page != $current_page_number)
echo "<a href=\"?page=$page" . (($query_string) ? "&$query_string" : "") . "\">";
echo "$page ";
require_once('inc/database.php');
define("NUMBER_PER_PAGE", 5); //number of records per page of the search results
$page = ($_GET['page']) ? $_GET['page'] : 1;
$start = ($page-1) * NUMBER_PER_PAGE;
$sql = "SELECT * FROM members WHERE 1=1";
$total_records = mysql_num_rows(mysql_query($sql));
//we limit our query to the number of results we want per page
$sql .= " LIMIT $start, " . NUMBER_PER_PAGE;
// we display our pagination at the top of our search results
pagination($page, $total_records, "id=$id&username=$username&email=$email");
$loop = mysql_query($sql)
or die ('cannot run the query because: ' . mysql_error());
while ($record = mysql_fetch_assoc($loop))
echo "<br/>{$record['id']}) " . stripslashes($record['username']) . " - {$record['email']}";
echo "<center>" . number_format($total_records) . " search results found</center>";
if ($page != $current_page_number)
echo "</a>";
$page++;
Pagination is one of those things that has been done so many times that you're better off figuring out how to use a pre made class like this one http://code.tutsplus.com/tutorials/how-to-paginate-data-with-php--net-2928
The basics of what you need to do are calculate how many links you want to see on either side of the elipses ... and then make loops to create those links. The ceil() function may be new for you, but it returns a fraction always rounded up.
$buffer = 3;
$results_per_page = 5;
$page = ($_GET['page']) ? $_GET['page'] : 1;
$start = ($page-1) * $results_per_page;
$sql = "SELECT * FROM members WHERE 1=1";
$total_records = mysql_num_rows(mysql_query($sql));
$total_pages = ceil(intval($total_records) / $results_per_page);
for ($x = $page - $buffer; $x < $page; $x++){
echo " $x";
}
echo " ... ";
for ($x = $total_pages - $buffer; $x <= $total_pages; $x++){
echo " $x";
}
This quick little bit of code does not take in to consideration result sets small enough to fit all links in to one line. Which is why I suggest using the pagination classes that exist already.

How to limit MySQL query result to specific results?

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

"Displaying X to Y of Z results" using Codeigniter pagination library?

I am, using the Codeigniter pagination library,
I am wondering how I can grab the number of the first and last items displayed using the pagination class?
So, if I had 12 results, and per_page was set to 5. I would want
Page 1: Displaying 1 to 5 of 12 results
Page 2: Displaying 6 to 10 of 12 results
Page 3: Displaying 11 to 12 of 12 results.
Keeping it simple.
You need 3 variables. Result start, result end (in the page, not the whole) and total result.
You already know the total results (from the pagination). Let's call it $total.
so, now get the current page ($curpage) value from CI instance. Then,
$result_start = ($curpage - 1) * $per_page + 1;
if ($result_start == 0) $result_start= 1; // *it happens only for the first run*
for $result_end, you just need to add the per page value but considering it'll be 1 less,
$result_end = $result_start+$per_page-1;
if ($result_end < $per_page) // happens when records less than per page
$result_end = $per_page;
else if ($result_end > $total) // happens when result end is greater than total records
$result_end = $total;
send all those 3 values to view.
echo "displaying $result_start to $result_end of $total";
itachi's solution works great except you need to handle the case where the last page has less than $per_page elements.
if ($result_end > $total) {
$result_end = $total;
}
In CodeIgniter Controller file
$params['limit'] = 15;
$params['offset'] = ($this->input->get('per_page')) ? $this->input->get('per_page') : 0;
$config = $this->config->item('pagination');
$config['per_page'] = $params['limit'];
$config['base_url'] = site_url('cy_controller/action?');
$config['total_rows'] = $this->abcd_model->get_count($params);
$this->pagination->initialize($config);
$data['merchant'] = $this->abcd_model->get_all($params);
$countMerchant = count($data['merchant']);
if ($params['offset'] == 0) {
$find_total_record = $countMerchant;
} else {
$valuec = $params['offset'] + $params['limit'];
if ($valuec > $config['total_rows'])
$find_total_record = $params['offset'] + $countMerchant;
else
$find_total_record = $params['offset'] + $params['limit'];
}
$per_page_total = $find_total_record;
$initial = $params['offset'] == 0 ? 1 : $params['offset'];
$data['showing'] = "Showing " . $initial . " to " . $per_page_total . " of " . $config['total_rows'] . " results";
$data['_view'] = 'cy_controller/action';
$this->load->view('layouts/main', $data);
And in view file
<div class="pull-left">
<?php echo $showing; ?>
</div>

pagination fixing php mysql

this pagination only for next and previous wallpaper/ query , but its show also empty rows,
how to fix it?
<?php
// Figure out the limit for the query based
// on the current page number.
$from = (($walpaperid * $max_results) - $max_results);
// Figure out the total number of results in DB:
$total_results = mysql_result(mysql_query("SELECT COUNT( * ) AS `Rows` , `wallpaperid`
FROM `wallpaper` ORDER BY `wallpaper`.`wallpaperid` ASC"),0) or die(mysql_error());
// Figure out the total number of pages. Always round up using ceil()
$total_pages = ceil($from / $max_results);
// Build Page Number Hyperlinks
// Build Previous Link
if($wallpaperid > 1){
$prev = ($wallpaperid - 1);
echo "<Previous Page ";
}
for($i = 1; $i <= $total_pages; $i++){
if(($pagenum) == $i){
echo "<strong>$i</strong> ";
} else {
echo "<a class = 'mlnk' href=\"$siteurl3/$cat_url-$catid-$i.php\">$i</a> |";
}
}
// Build Next Link
if($wallpaperid < $total_pages){
$next = ($wallpaperid + 1);
echo "Next Page>";
}
?>
Correct your code to figure out the number of pages:
$total_pages = ceil($total_results / $max_results);

pagination incrementing problem

I have the following code, which is the basis for pagination in a larger application. However, it does not work, as although I should be obtaining the value of pg from the url, pg never goes higher than 2. For some reason, next = pg+1; seems to always see pg as 1, regardless of what is passed on the url. It is a similar problem with last. I assume I am overriding the value obtained from GET, but I am unsure where.
The problem seems to be in how I am working out $max and the limit, as instead of 0, 10, -10, 10 gets passed. Also the ifcode before $max does not seem to succeed in stopping pg from being 0.
<?php
if (isset($_GET["pg"])) {
$pg = $_GET["pg"];
} else $pg = 1;
$con = mysql_connect("localhost","","");
if(!$con) {
die('Connection failed because of' .mysql_error());
}
mysql_select_db("ebay",$con);
if ($pg < 1) {
$pg = 1;
} elseif ($pg > $last) {
$pg = $last;
}
$table = 'AUCTIONS';
$page_rows = 10;
$max = ' limit ' .($pg - 1) * $page_rows .', ' .$page_rows;
$rows = getRowsByArticleSearch($query, $table, $max);
$rowcount = count($rows);
echo $rowcount;
$last = ceil($rowcount/$page_rows);
$page_rows = 10;
$rowcount = 2;
// Would normally obtain the number of rows returned, but database stuff is snipped for brevity
$last = ceil($rowcount/$page_rows);
if ($pg < 1) {
$pg = 1;
} elseif ($pg > $last) {
$pg = $last;
}
$self = htmlspecialchars($_SERVER['PHP_SELF'],ENT_QUOTES,'utf-8');
echo " <a href='$self?pg=1'> <<-First</a> ";
$previous = $pg-1;
echo " <a href='$self?pg=$previous'> <-Previous</a> ";
echo "---------------------------";
$next = $pg+1;
echo " <a href='$self?pg=$next'>Next -></a> ";
echo " <a href='$self?pg=$last'>Last ->></a> ";
The code is correct, however, the data is wrong.
When you have
$page_rows = 10;
$rowcount = 2;
it actually means, that you have 2 rows displayed on pages which will display 10 rows each. This makes it 1 page in total.
Change it to
$page_rows = 10;
$rowcount = 200;
and voila, you will get your pagination.
Here's your problem:
$last = ceil($rowcount/$page_rows);
That's setting $last to be 1, and then you have:
if ($pg > $last) {
$pg = $last;
}
Edit: I wonder if you meant this, instead:
$last = ceil($page_rows/$rowcount);
Edit again: as per Cassy's answer, you probably really just need to set the right values for these variables:
$page_rows = 10;
$rowcount = 2;
based on the now revised question:
$rowcount = count($rows);
will naturally always return 10, as you're limiting the result
... LIMIT 10;
But this might help:
SQL CALC FOUND ROWS
Example:
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
-> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
The first query will still return your articles, while the second will return the number of rows the previous select would have had if not using the LIMIT clause.
Hope that helps.

Categories