I am trying to make pagination from one post to the next post in a single blog post. The problem is that when I open an article with ID-1 and I click on the 'next' button I get a blank/empty page.
This is the post page, which gets the ID of the chosen post in blog.php. This is what I have so far. Any suggestions?
<?php
// include database connection
require_once 'database.inc.php';
$pdo = Database::connect();
if(isset($_GET['post_id']) && is_numeric($_GET['post_id'])){
$post_id = $_GET['post_id'];
// page is the current page, if there's nothing set, default is page 1
$page = isset($_GET['page']) ? $_GET['page'] : 1;
// set records or rows of data per page
$recordsPerPage = 1;
// calculate for the query LIMIT clause
$fromRecordNum = ($recordsPerPage * $page) - $recordsPerPage;
// select all data
$query = "SELECT * FROM posts WHERE post_id = $post_id LIMIT {$fromRecordNum}, {$recordsPerPage}";
$stmt = $pdo->prepare( $query );
$stmt->execute();
//this is how to get number of rows returned
$num = $stmt->rowCount();
//check if more than 0 record found
if($num>0){
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
echo '
// post body ';
}
}
// *************** <PAGING_SECTION> ***************
// ***** for 'first' and 'previous' pages
if($page>1){
// ********** show the previous page
$prev_page = $page - 1;
echo "
<a href='" . $_SERVER['PHP_SELF'] . "?page={$prev_page}'>
<div class='prev-btn control-nav text-left'>
<h5>Previous Post</h5>
</div>
</a>";
}
// find out total pages
$query = "SELECT COUNT(*) as total_rows FROM posts";
$stmt = $pdo->prepare( $query );
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$total_rows = $row['total_rows'];
$total_pages = ceil($total_rows / $recordsPerPage);
if($page<$total_pages){
// ********** show the next page
$next_page = $page + 1;
echo "<a href='" . $_SERVER['PHP_SELF'] . "?page={$next_page}'>
<div class='next-btn control-nav text-right'>
<h5>Next Post</h5>
</div>
</a>";
}
}
?>
It's not very clear from your question, but I think your problem is this, your code requires the post_id parameter to be set:
if(isset($_GET['post_id']) && is_numeric($_GET['post_id'])){
$post_id = $_GET['post_id'];
}
But in your next and prev page links, you're not setting a post_id parameter:
echo "<a href='" . $_SERVER['PHP_SELF'] . "?page={$next_page}'>
<div class='next-btn control-nav text-right'>
<h5>Next Post</h5>
</div>
</a>";
Your code is inherently relying on a single post being shown, as determined by the post_id. Here's what I suggest, change:
// select all data
$query = "SELECT * FROM posts WHERE post_id = $post_id LIMIT {$fromRecordNum}, {$recordsPerPage}";
to:
// select all data
$query = "SELECT * FROM posts LIMIT {$fromRecordNum}, {$recordsPerPage}";
of course, then, you won't be able to show a specific post, but then again it's hard to know what you're actually trying to achieve here.
Could you show it in a working website? It would be easier to tell what is wrong then, but from the code it looks like you are making the url wrong in your anchor href part.
$prev_page = $post_id - 1;
<a href='" . $_SERVER['PHP_SELF'] . "?post_id={$prev_page}'>
<div class='prev-btn control-nav text-left'>
<h5>Previous Post</h5>
</div>
</a>"
$next_page = $post_id + 1;
and the link is there made in same manner as previous one
as i am not sure what your server php self is returning and you shouldnt be adding the second ? symbol in it, if it already had it and u should use & i think for get parameters as ? is only used once after the script file name once. Or you are either missing the ID in your url.
Also blank/empty page might be crashing the script on that page and if u have errors turned off you wont see it in webpage and will have to go to your php errors log file to look for them
EDIT: as block quote wasnt showing correctly.
It is because first you get $post_id but then in the links you put $page which doesn't contain your ID. Try to change your nex&prev links like this:
<a href='" . $_SERVER['PHP_SELF'] . "?post_id=".$prev_page."'>
<a href='" . $_SERVER['PHP_SELF'] . "?post_id=".$next_page."'>
Also don't forget to change the line for $page here:
$page = isset($_GET['page']) ? $_GET['page'] : 1;
to this
$page = isset($_GET['post_id']) ? $_GET['post_id'] : 1;
This should do the trick.
Related
I've set up a search of my database with pages. There are two searches performed on this page, one for users and one for pets, but for now I am trying to get it to work with the pet search only. The search itself functions, and the results display properly for page 1 with the appropriate amount of linked pages after. My problem comes in when I try to go beyond the first page. I have checked the search itself and it brings up results in my database, but clicking the page link results in a 'No results' message. Here is my initial setup:
<?php
if (!isset ($_GET['page']) ) {
$page = 1;
} else {
$page = $_GET['page'];
}
$results_per_page = 10;
$page_first_result = ($page-1) * $results_per_page;
$num_results = 0;
include("includes/header.php"); // This is where the first search is performed to check for number of rows
if (!empty($pet_search_result)) {
$number_of_result = mysqli_num_rows($pet_search_result);
$num_results = mysqli_num_rows($pet_search_result);
}
else if (!empty($user_search_result)) {
$number_of_result = mysqli_num_rows($user_search_result);
}
else {
$number_of_result = 0;
}
$number_of_page = ceil ($num_results / $results_per_page);
?>
This is of course followed by the search where users enter parameters. This search works perfectly without pagination. After those have been entered, the code says this:
$queryConditions = $queryConditions . ' LIMIT ' . $results_per_page . ' OFFSET ' . $page_first_result;
$pet_search_result2 = mysqli_query($con, "SELECT * from pets WHERE $queryConditions");
Results are then displayed, and here is where the problem hits.
for($page = 1; $page<= $number_of_page; $page++) {
echo " <a style ='color: white;' href='?page=$page'> $page </a> | ";
}
Clicking the link to page 2 or any other page leaves the user on the search page with no results shown. I have checked and the proper page number is picked up on page 2, the offset is correct, and the search itself turns up the appropriate results when performed directly in the database.
I have tried using
htmlentities($_SERVER['PHP_SELF'])
and
$_SERVER['PHP_SELF']
so that it read:
echo " <a href='" . htmlentities($_SERVER['PHP_SELF']) . "?page=$page'> $page </a> | ";
or
echo " <a style ='color: white;' href='" . $_SERVER['PHP_SELF'] . "?page=$page'> $page </a> | ";
as the redirect url, and none of these worked. I was expecting clicking page 2 to show me the search page with the second set of 10 results. Instead it acts as if no search has been performed.
I am building a website and I want to add "previous" & "next" buttons to send the user to the previous or the next page. So i tried this:
where 'pid' is the 'post id' I did the same thing for 'next page' button
it worked... but it continues even if the page with that ID doesnt exist. im wondering if I could get some help with 'checking if current page is first row or last row.'.
Here's my code:
<?php
require('connect.php');
if(preg_match('/[^0-9]/i', $_REQUEST['pid'])) {
echo '<div style="margin:50px auto;" class="warning_msg">WARNING: !! Illegal character detected !! >> <b>'.$_REQUEST['pid'].'</b></div>';
} else {
$post_ = $dbh->query('SELECT * FROM `posts` WHERE `id`='.$dbh->quote($_REQUEST['pid']).'')->fetch();
echo '<div class="_header_ p_header_ disable_padding">
'.$post_['title'].'
<a href="?p=posts&pid='.($_REQUEST['pid']+1).'" class="next_page fa fa-hand-o-right" title="Next Post" ></a>
</div>
<div>'.$post_['article'].'</div>
<div class="_footer_">posted by <i>'.$post_['author'].'</i> on ยป '.date('M d Y H:m:i', strtotime($post_['post_time'])).'</div>';
}
?>
EDIT (SOLVED):
to find the first & last row i used a single query
$page = $dbh->query('SELECT MIN(id), MAX(id) FROM `posts`')->fetch();
and used like :
/* if current post id is equals to last id from posts */
if($_REQUEST['pid'] == $page[1]) { $next_page = $_REQUEST['pid'].'#';}
else { $next_page = ($_REQUEST['pid']+1); }
/* if current post id is equals to first id from posts */
if($_REQUEST['pid'] == $page[0]) { $prev_page = $_REQUEST['pid'].'#';}
else { $prev_page = ($_REQUEST['pid']-1); }
<?php
$lastpage = 10;
$ppage = isset($_REQUEST['pid']) && $_REQUEST['pid'] > 1 ? ($_REQUEST['pid']-1) : 0;
$npage = isset($_REQUEST['pid']) && $_REQUEST['pid'] < $lastpage ? ($_REQUEST['pid']+1) : $lastpage;
?>
Here i put a constant value 10 for last page.Instead of that you have to find outlast page id and replace that.Php pagination scripts are also available to find out first and last pages..
I'm currently working on producing a basic content management system. In this code I'm grabbing a list of pages from the database 'posts' and then echoing them out. The purpose of the list is for users to be able to select an existing page and then edit the title & content, however I'm unsure on how I can take data from the selected link and then make my page-edit.php show the correct content to edit accordingly. I've assigned the variable $i to each of the anchor tags which increments throughout the while loop, ideally I'd use $i to SELECT the correct page from the database. I'd like to avoid using jQuery, although I'm assuming that's going to be suggested. Any insight would be great, thanks in advance.
<?php
$connection = mysql_connect('localhost', 'root', 'root');
mysql_select_db('posts');
$query = "SELECT * FROM pages";
$result = mysql_query($query);
$i = 0;
while($row = mysql_fetch_array($result)){
$i++;
echo '' . $row['page_title'] . ' - ' . $i . '' . '</br>';
}
mysql_close();
?>
Use the $i as a GET id variable in the link within the while loop:
echo '<a href="edit-page.php?id=' . $i . '>' . $row['page_title'] . ' - ' . $i . '</a>' . '</br>';
Then you can check for $_GET['id'] so that you know what id/page is to be edited and get the data for that from the database:
if (!empty($_GET['id'])) {
$query = 'SELECT * FROM pages WHERE id=' . $_GET['id'];
...
// Show the form populated with data from the above query.
}
I've kept this very simple to get you started.
Don't forget to look into protecting against SQL Injection and moving away from the deprecated MySQL API to use the MySQLi API or MySQL PDO.
Using this method, you'll need a to make an edit page for each page.
Main php file
<?php $db = mysqli_connect("localhost","user","pass","name");
foreach($this->db->query("SELECT * FROM pages") as $row): ?>
<a onclick="loadPage(<?php echo $row['id']; ?>)">
<?php echo $row['page_title']; ?>
</a>
<?php endforeach; ?>
<script>
function loadPage(id){
$.get('handler.php', { param: id })
.done(function (loaded){
document.getElementById("example").innerHTML = loaded;
});
}
</script>
Handler php file
<?php if(isset($_GET['param'])):
foreach($this->db->query("SELECT * FROM pages") as $row):
catch($_GET['param']){
case 1:
require_once 'edit-data.php';
break;
case 2:
require_once 'edit-data-two.php';
break;
default:
break;
}
endforeach; ?>
edit-data.php = edit the page X
edit-data-two.php = edit the page Y
I'm using this while statement to show all contents of database...
$sql = mysql_query("SELECT id,question,date,user,numberofcomments,body,locked FROM questions ORDER BY id DESC");
while($row=mysql_fetch_assoc($sql)) {
echo '<div class="comment">';
echo '<div class="leftpart">';
echo "<div class='date'><img src='../assets/icons/Time-info.png'> ".ago($row['date']);
echo "</div><br><img src='../assets/icons/User-Info.png'> ".$row['user'];
echo "<br><img src='../assets/icons/Comments.png'> ".$row[numberofcomments];
echo '</div>';
echo '<div class="rightpart-topic">';
if($row['locked']==1) { echo '<img src="../assets/icons/Lock.png" /> ';
}
echo ''.$row['question'].'';
echo '<br>'.substr($row['body'],0,70).'...';
echo '</div>';
echo '</div>';
}
I want to show only 10 rows then have links to show the rest (as in page 1,2,3,4, last type thing). How would I go about doing that? It would help if you could also explain your code as it would be greatly appreciated. It helps my learning process.
Thanks!
You need to do a LIMIT in your query using some sort of passed $_GET variable.
$start=0;
$limit = 10;
$page = (isset($_GET['page']) ? : 0));
$start = $page * $limit;
$sql = mysql_query("SELECT id,question,date,user,numberofcomments,body,locked FROM questions ORDER BY id DESC LIMIT {$start},{$limit}");
Should be pretty self explanatory.
If there is not page variable set then you are viewing page 0, or the first 10 results of your database query. If page = 1 then you are going to be viewing $page (value=1) * $limit (10) = $start (now value of 10), which will give you results 10-20 or page 1. etc.
So provide your user a button which can link them to a hard paginated link, or do it ajax.
Each url will need to be like so:
http://wwww.yoursite.com/somepage.php?page=1
Efficiency aside, you could simply set a counter and check if it value Is greater than 10 during the loop. If so, add a 'hidden' class to the parent div. That class would use display:none;
Hey, I am still trying to allow multiple filters to be selected for my pagination script but not sure how to do it being very new to php and programing in general.
So in my pagination, when a user clicks the 'marketing' button(link) it queries the database just for the category that = marketing. The same goes for the other 2 filter buttons as seen in the script below. (automotive, sports).
The problem is, I want to be able to select multiple filters like only marketing and auomotive or automotive and sports, for example if I click the marketing filter and then the automotive, it would display the categories that equal marketing, and automotive.
I have no idea how to accomplish this, so I have come to the experts to help me out.
This is the script I am working on:
<h3>Filter results by:</h3>
<a href='pagi_test.php?category=marketing'>marketing</a>
<a href='pagi_test.php?category=automotive'>automotive</a>
<a href='pagi_test.php?category=sports'>sports</a>
<br />
<h3>Results:</h3>
<?php
//connecting to the database
$error = "Could not connect to the database";
mysql_connect('localhost','root','root') or die($error);
mysql_select_db('ajax_demo') or die($error);
//max displayed per page
$per_page = 3;
//get start variable
$start = $_GET['start'];
$category = mysql_real_escape_string($_GET['category']);
//count records
$record_count = mysql_num_rows(mysql_query("SELECT * FROM explore WHERE category='$category'"));
//count max pages
$max_pages = $record_count / $per_page; //may come out as decimal
if (!$start)
$start = 0;
//display data
$get = mysql_query("SELECT * FROM explore WHERE category='$category' LIMIT $start, $per_page");
?>
<table width="800px">
<?php
while ($row = mysql_fetch_assoc($get))
{
// get data
$id = $row['id'];
$site_name = $row['site_name'];
$site_description = $row['site_description'];
?>
<tr>
<td><?php echo $id; ?></td>
<td><?php echo $site_name; ?></td>
<td><?php echo $site_description; ?></td>
</tr>
<?php
}
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
//show prev button
if (!($start<=0))
echo "<a href='pagi_test.php?category=$category&start=$prev'>Prev</a> ";
//show page numbers
//set variable for first page
$i=1;
for ($x=0;$x<$record_count;$x=$x+$per_page)
{
if ($start!=$x)
echo " <a href='pagi_test.php?category=$category&start=$x'>$i</a> ";
else
echo " <a href='pagi_test.php?category=$category&start=$x'><b>$i</b></a> ";
$i++;
}
//show next button
if (!($start>=$record_count-$per_page))
echo " <a href='pagi_test.php?category=$category&start=$next'>Next</a>";
?>
Any help on this would be great. Thank you.
-- EDIT --
If anyone has a better method of doing a pagination system with multiple filters than the one above, please let me know.
While selecting second filter u can add the category
ex:
At first ur variable $category has
$category="Marketing";
When user filter with another category suppose automotive then add it to $category with a delimeter,Now
$category="Marketing:Automotive";
when u access thru GET use explode:
$cat=explode(":",$_GET['category']);
and write your condition
$condition="category=category[0]";
for($i=1; $i<sizeof($cat); $i++)
{
$condition="AND category=$cat[$i]";
}
$where="WHERE $condition";
use $where in ur query, like
$record_count = mysql_num_rows(mysql_query("SELECT * FROM explore $where"));
I see two separate issues
How to allow the user to select more than one category to filter by
How to propagate those choices to the pagination links
Each for which I have a solution!
How to allow the user to select more than one category to filter by
A form is going to be the most direct approach.
<h3>Filter results by:</h3>
<form action="pagi_test.php" method="GET">
<input type="checkbox" name="category[]" value="marketing" id="cat_marketing"/>
<label for="cat_marketing">Marketing</label>
<br/>
<input type="checkbox" name="category[]" value="automotive" id="cat_automotive"/>
<label for="cat_automotive">Automotive</label>
<br/>
<input type="checkbox" name="category[]" value="sports" id="cat_sports"/>
<label for="cat_sports">Marketing</label>
<br/>
<input type="submit" value="Filter!" />
</form>
Now, $_GET['category'] will be an array of every category that was selected.
$categories = $_GET['category'];
$inClause = "'" . implode( "','", array_map( 'mysql_real_escape_string', $categories ) ) . "'";
//count records
$record_count = mysql_num_rows(
mysql_query( "SELECT * FROM explore WHERE category IN($inClause)" )
);
Of course, you'd probably want to add a check here to make sure $categories isn't empty before you execute the query.
You'll need to modify the actual selection query as well
//display data
$get = mysql_query("SELECT * FROM explore WHERE category IN($inClause) LIMIT $start, $per_page");
Bingo! Now that part is done!
How to propagate those choices to the pagination links
Since we already have an array of the categories selected stored in $categories, this will be trivial using http_build_query().
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
// Get the categories in an HTML-safe array
$requestVars = array_map( 'htmlspecialchars', $categories );
//show prev button
if (!($start<=0))
{
$requestVars['start'] = $prev;
echo 'Prev ';
}
//show page numbers
//set variable for first page
$i=1;
for ( $x = 0; $x < $record_count; $x = $x + $per_page )
{
$requestVars['start'] = $x;
if ( $start != $x )
{
echo ''. $i .' ';
} else {
echo '<b>'. $i .'</b> ';
}
$i++;
}
//show next button
if (!($start>=$record_count-$per_page))
{
$requestVars['start'] = $next;
echo 'Next ';
}
Now, there are still holes in this implementation.
Since the <form> is printed to the page before the rest of the logic, there's no way to pre-select the checkboxes that represent the current filter choices. Which you could definitely change.
Also, you have categories as literal strings in the PHP script - they would really be better in their own table in the database.
The way you retrieve a count for the entire data set is inefficient - it sends the entire data set over the wire to PHP, which then is responsible for determining the record count. It's much better to run a separate query that uses SELECT count(*) ... instead.