PHP Pagination Link Generation - php

I have this script below which i found on SO to generate pagination and broadly speaking, its working great, however because its a cut and paste job from me, i don't understand how to actually generate the links which are echoed in the script with the variable $pagination.
What it echos is:
1< a href="index.php?page=2">2< a href="index.php?page=3">3< a hr_ef="?page=2"> Next
None of which are working (clickable) links, and i also want to be able to style them so would rather output them in HTML, rather than a php echo, something like:
<p><?php 1< a href="index.php?page=2">2< a href="index.php?page=3">3< a hr_ef="?page=2"> Next ?> </p>
Below is the script i'm using:
<?php
/* Set current, prev and next page */
$page = (!isset($_GET['page']))? 1 : $_GET['page'];
$prev = ($page - 1);
$next = ($page + 1);
/* Max results per page */
$max_results = 10;
/* Calculate the offset */
$from = (($page * $max_results) - $max_results);
/* Query the db for total results.*/
$result = mysql_query("...");
$total_results = mysql_num_rows($result);
$total_pages = ceil($total_results / $max_results);
$pagination = '';
/* Create a PREV link if there is one */
if($page > 1)
{
$pagination .= '< a href="?page='.$prev.'">Previous</a> ';
}
/* Loop through the total pages */
for($i = 1; $i <= $total_pages; $i++)
{
if(($page) == $i)
{
$pagination .= $i;
}
else
{
$pagination .= '< a href="index.php?page='.$i.'">'.$i.'</a>';
}
}
/* Print NEXT link if there is one */
if($page < $total_pages)
{
$pagination .= '< a hr_ef="?page='.$next.'"> Next</a>';
}
/* Below is how you query the db for ONLY the results for the current page */
$query ="SELECT * FROM ... LIMIT $from, $max_results";
$result=mysql_query($query) or die(mysql_error());
$rsjobinfo=mysql_fetch_assoc($result);
do {?>
<div>
[Individual Row Output]
</div>
<?php } while ($rsjobinfo=mysql_fetch_assoc($result));
echo $pagination;
?>
Can someone help? I imagine its a small fix but as always, would appreciate a kick in the right direction.
Thanks
Dan

Maybe it's just an editing error, but in your output the <a>-tags don't seem to be closed again. Also, there should be no space like < a> at the beginning of the tag. And < a hr_ef= ... is obviously wrong.
In order to style them, you can add a class attribute to the tags while building the string and do the style-stuff in css.

Related

PHP Pagination Script Not Showing Correct Content For Page Number

I've built a php script to navigate my blog pages back and forwards, but the first page shows up correctly, but when I navigate to the next page it shows the correct number, but still shows the same content as before. Then, the next button keeps showing the current page.
Here is my script:
$publication = "magazine";
$ppp = "6";
if(isset($_GET["id"])){$id = $_GET["id"];}else{
header("Location: ".$url."");
exit();
}
if(isset($_GET["currentpage"])){$currentpage = $_GET["currentpage"];}else{
header("Location: ".$url."");
exit();
}
$count_sql = "SELECT id FROM publication_posts WHERE publication = '".$publication."' AND issue = '".$id."'";
$count_res = mysqli_query($con, $count_sql);
$count_total = mysqli_num_rows($count_res);
//If None, Then Exit
if($count_total == 0){
header("Location: ".$url."");
exit();
}
$display_limit = $ppp;
$totalpages = ceil($count_total / $display_limit);//$rowsperpage
$currentpage = $totalpages;
$offset = ($totalpages - 1) * $display_limit;//$rowsperpage
if($currentpage == "0"){
header("Location: ".$url."/issue/".$id."/".$totalpages."");
exit();
}
$posts_sql = "SELECT * FROM publication_posts WHERE publication = '".$publication."' AND issue = '".$id."' ORDER BY id DESC LIMIT ".$offset.", ".$display_limit."";
Another thing that I notice here is that if I set the current page to 0, it still shows issue/id/0, whereas this should redirect to the $totalpages
Anyone know where the problem is?
Here is my pagination:
<?php
// range of num links to show
$range = 0;
if ($currentpage != $totalpages) {
// get next page
$nextpage = $currentpage + 1;
// echo forward link for next page
$link_next = "<div class=\"pagiCell pagiNext fadeOut\"></div>";
}
else{
$link_next = "<div class=\"pagiCell pagiNextX\"></div>";
}
?>
<?php
// range of num links to show
$range = 0;
if ($currentpage > 1) {
// get previous page
$prevpage = $currentpage - 1;
// echo forward link for next page
$link_prev = "<div class=\"pagiCell pagiPrev fadeOut\"></div>";
}
else{
$link_prev = "<div class=\"pagiCell pagiPrevX\"></div>";
}
?>
<?php
$link_refresh = "<div class=\"pagiCell pagiRefresh fadeOut\"></div>";
?>
<?php
$randpage = rand(1,$totalpages);
$link_random = "<div class=\"pagiCell pagiRandom fadeOut\"></div>";
?>
Short URL : localhost/publication/magazine/issue/1/1
Long URL : localhost/publication/magazine/issue?id=1&currentpage=1
I think your problem is that your $currentpage var is a string and you are doing math with it without converting it. You should type cast it: PHP: Type Juggling
$nextpage = $currentpage + 1;
becomes $nextpage = (int)$currentpage + 1;
Like Magnus Eriksson told before, you are not checking your user inputs for security issues. Testing your variables for expected values imply that, e.g. PHP: is_int

Setting the default pagination page (Something to do with the loop?)

I am currently using the plugin WP-CommentNavi for comments pagination but whenever a page is clicked it goes to the highest comments page (oldest comments). My comments are purposely displayed newest first and therefore I need the default pagination page to be 1 whenever a link is clicked.
I notice there is the same default for other pagination plugins too whereby the highest pagination page (ie if there are 5 pages) page 5 is displayed.
At the moment when I load page tellhi####.com/newcastle the page that will be loaded is tellhi####.com/newcastle/comment-page-2/ whereas I want tellhi####.com/newcastle/comment-page-1/ to be loaded
I can't be sure this is the relevant code to what I am trying to achieve but I feel the answer might lie in here (below). If not, please tell me and disregard this code.
### Function: Comment Navigation: Boxed Style Paging
function wp_commentnavi($before = '', $after = '') {
global $wp_query;
$comments_per_page = intval(get_query_var('comments_per_page'));
$paged = intval(get_query_var('cpage'));
$commentnavi_options = get_option('commentnavi_options');
$numcomments = intval($wp_query->comment_count);
$max_page = intval($wp_query->max_num_comment_pages);
if(empty($paged) || $paged == 0) {
$paged = 1;
}
$pages_to_show = intval($commentnavi_options['num_pages']);
$pages_to_show_minus_1 = $pages_to_show-1;
$half_page_start = floor($pages_to_show_minus_1/2);
$half_page_end = ceil($pages_to_show_minus_1/2);
$start_page = $paged - $half_page_start;
if($start_page <= 0) {
$start_page = 1;
}
$end_page = $paged + $half_page_end;
if(($end_page - $start_page) != $pages_to_show_minus_1) {
$end_page = $start_page + $pages_to_show_minus_1;
}
if($end_page > $max_page) {
$start_page = $max_page - $pages_to_show_minus_1;
$end_page = $max_page;
}
if($start_page <= 0) {
$start_page = 1;
}
if($max_page > 1 || intval($commentnavi_options['always_show']) == 1) {
$pages_text = str_replace("%CURRENT_PAGE%", number_format_i18n($paged), $commentnavi_options['pages_text']);
$pages_text = str_replace("%TOTAL_PAGES%", number_format_i18n($max_page), $pages_text);
echo $before.'<div class="wp-commentnavi">'."\n";
switch(intval($commentnavi_options['style'])) {
case 1:
if(!empty($pages_text)) {
echo '<span class="pages">'.$pages_text.'</span>';
}
if ($start_page >= 2 && $pages_to_show < $max_page) {
$first_page_text = str_replace("%TOTAL_PAGES%", number_format_i18n($max_page), $commentnavi_options['first_text']);
echo ''.$first_page_text.'';
if(!empty($commentnavi_options['dotleft_text'])) {
echo '<span class="extend">'.$commentnavi_options['dotleft_text'].'</span>';
}
}
previous_comments_link($commentnavi_options['prev_text']);
for($i = $start_page; $i <= $end_page; $i++) {
if($i == $paged) {
$current_page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $commentnavi_options['current_text']);
echo '<span class="current">'.$current_page_text.'</span>';
} else {
$page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $commentnavi_options['page_text']);
echo ''.$page_text.'';
}
}
next_comments_link($commentnavi_options['next_text'], $max_page);
if ($end_page < $max_page) {
if(!empty($commentnavi_options['dotright_text'])) {
echo '<span class="extend">'.$commentnavi_options['dotright_text'].'</span>';
}
$last_page_text = str_replace("%TOTAL_PAGES%", number_format_i18n($max_page), $commentnavi_options['last_text']);
echo ''.$last_page_text.'';
}
break;
case 2;
echo '<form action="'.admin_url('admin.php?page='.plugin_basename(__FILE__)).'" method="get">'."\n";
echo '<select size="1" onchange="document.location.href = this.options[this.selectedIndex].value;">'."\n";
for($i = 1; $i <= $max_page; $i++) {
$page_num = $i;
if($page_num == 1) {
$page_num = 0;
}
if($i == $paged) {
$current_page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $commentnavi_options['current_text']);
echo '<option value="'.clean_url(get_comments_pagenum_link($page_num)).'" selected="selected" class="current">'.$current_page_text."</option>\n";
} else {
$page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $commentnavi_options['page_text']);
echo '<option value="'.clean_url(get_comments_pagenum_link($page_num)).'">'.$page_text."</option>\n";
}
}
echo "</select>\n";
echo "</form>\n";
break;
}
echo '</div>'.$after."\n";
}
}
In short I need, anytime a page is clicked, for the comments pagination to be on page 1, not the highest page available. Just so you know I have tried the discussion settings on the wordpress dashboard. Nothing on google either!
Failing a full answer, does anyone know the actual php code that determines what pagination page is loaded by default?
I received this response via an e-mail but due to my PHP knowledge am unable to implement it, any ideas? ...
Just reverse the loop. That'll fix it. Here's the relevant part:
http://pastie.org/8166399 You need to go back, i.e. use $i--
Would this change the default start page or just reverse the comments? Hope I have been clear in my question! Will appreciate any response at all.
Thanks in advance, Paul
The option was in Wordpress all along. See picture: http://oi40.tinypic.com/35aj3pt.jpg
If anyone has the answer to the specific code you manipulate, still answer the question here because someone doing this without Wordpress could very well encounter this problem also.

Selecting records in a MySQL database where id != 0

I'm having trouble with my site.
I have a photographs table with id's. THis table is populated when a user uploads a file to the server, which is fine. I also have a forum where images can be posted, and the images are sent to the same photograph table. On the homepage there is a section where one of the photographs from this table shows up with Pagination links below it.
Now when someone posts to the forum and they do not include an image it breaks. That thread won't show up because it's looking for the photo_id of 0, which didn't exist. So I uploaded a dummy image, changed the id value to zero and tried
$sql = "SELECT * FROM photographs HAVING id != 0 ";
$sql .= "LIMIT {$per_page} ";
$sql .= "OFFSET {$pagination->offset()}";
Which worked, the image no longer shows up, but the pagination still thinks that there is a record there. It shows a link for that image and when a user clicks on it it breaks and removes a bunch of other links and it's a mess.
Is it possible to Select everything from the database but not the 0 record, or maybe remove the link from the pagination links? Here is the code:
//1. the current page number ($current_page)
$page = !empty($_GET['page']) ? (int)$_GET['page'] : 1;
//2. records per page ($per_page)
$per_page = 1;
//3. total record count ($total_count)
$total_count = Photograph::count_all();
//Find all photos
//use Pagination instead
//$photos= Photograph::find_all();
$pagination = new Pagination($page, $per_page, $total_count);
//Instead of finding all records, just find the records
//for this page
$sql = "SELECT * FROM photographs HAVING id != 0 ";
$sql .= "LIMIT {$per_page} ";
$sql .= "OFFSET {$pagination->offset()}";
$photos = Photograph::find_by_sql($sql);
//Need to add ?page=$page to all links we want to
//maintain the current page(or store $page in $session)
?>
<div id="right">
<?php
foreach($photos as $photo):
?>
<h3 style="margin: 0;"></h3>
<div style="padding: 5px;">
<img src="<?php echo $photo->image_path(); ?>" width="200" alt="Photo Share Photo" />
<p align="center"><?php echo $photo->caption; ?></p>
</div>
<?php }
endforeach;
?>
<div id="pagination" style="clear: both;" align="center">
<?php
if($pagination->total_pages() > 1) {
if($pagination->has_previous_page()) {
echo "<a href=\"index.php?page=";
echo $pagination->previous_page();
echo "\">« Previous</a> ";
}
for($i=1; $i <= $pagination->total_pages(); $i++) {
if($i == $page) {
echo " <span class=\"selected\">{$i}</span> ";
} else {
echo " {$i} ";
}
}
if($pagination->has_next_page()) {
echo " <a href=\"index.php?page=";
echo $pagination->next_page();
echo "\">Next »</a> ";
}
}
?><br />
<div align="center">
Upload a new photograph
</div>
[EDIT]
Pagination code.
class Pagination {
public $current_page;
public $per_page;
public $total_count;
public function __construct($page=1, $per_page=20, $total_count=0){
$this->current_page = (int)$page;
$this->per_page = (int)$per_page;
$this->total_count = (int)$total_count;
}
public function offset() {
//Assuming 20 items per page:
//page 1 has an offset of 0 (1-1) * 20
// page 2 has an offset of 20 (2-1) * 20
//in other words, page 2 starts with item 21
return ($this->current_page - 1) * $this->per_page;
}
public function total_pages() {
return ceil($this->total_count/$this->per_page);
}
public function previous_page() {
return $this->current_page - 1;
}
public function next_page() {
return $this->current_page +1;
}
public function has_previous_page() {
return $this->previous_page() >= 1 ? true : false;
}
public function has_next_page() {
return $this->next_page() <= $this->total_pages() ? true : false;
}
}
I will look into the total_pages and get back to you if it works. I think I can just add WHERE id != 0 to the end of the count_all method. I don't think anything else uses it other than the photo share. I'll have to look into the code.
Thanks for your help with this.
DC
I simply added:
public static function count_all() {
global $database;
$sql = "SELECT COUNT(*) FROM ".self::$table_name." WHERE `id` **!= 0 AND `show` != 0";**
$result_set = $database->query($sql);
$row = $database->fetch_array($result_set);
return array_shift($row);
}
I added this to the photograph object. Now users can select whether or not that want their image to show in the photo sharing section, and if they don't upload an image with their post then it is automatically assigned the ID of 0. If this isn't clear and someone needs help with it, let me know.
As G-Nugget mentioned. NULL is better suited for this.
Your query also looks odd. The usual syntax is:
SELECT * FROM photographs WHERE id != 0
Having is used to apply filtering on GROUP BY queries.
Edit:
It also looks like you are using $total_count from pagination here:
$total_count = Photograph::count_all();
<snip>
for($i=1; $i <= $pagination->total_pages(); $i++) {
if($i == $page) {
echo " <span class=\"selected\">{$i}</span> ";
} else {
echo " {$i} ";
}
This will show a link for more pages than exist since $total_count includes the 0 record.

Conventions for combining PHP with HTML

I am studying PHP from a book. The author uses echo to output HTML. At first I thought that this was how it supposed to be done, but then I picked up a more "advanced" book. The author of the second book inserted PHP code between HTML rather then echo the whole thing. How is it done in large web development companies that work on large projects? Can you use either, or is one more accepted than the other?
Take this code for example:
<?php
//pagination
if ($pages > 1) {
//determine the current page
$current_page = ($start / $display) + 1;
//print out Previous Page button
if ($current_page != 1) {
?>
<div class="pages"><strong> < </strong></div>
<?php
}
//print the page numbers
for ($i = 1; $i <= $pages; $i++) {
if ($i == $current_page) {
?>
<div class="pages active"><span> <?php echo $i; ?> </span></div>
<?php
}
else {
?>
<div class="pages"><strong> <?php echo $i; ?> </strong></div>
<?php
}//end of $i = $current_page conditional
}//end of FOR loop
if ($current_page < $pages) {
?>
<div class="pages"><strong> > </strong></div>
<?php
}
}//end of pagination
include('includes/footer.php');
?>
Is that the correct way of doing it, or should I use something like this:
echo '<a href="view_users.php?s=' . ($display * ($i - 1)) .
'&p=' . $pages . '&sort=' . $sort . '">' . $i . '</a> ';
The reason why I'm asking is because I find it difficult to properly align the HTML when using the second technique, and I don't want to develop any bad habits early on.
The first method makes your code more readable. The second method is useful when you need to print some little amount of html code. Also you can use short open tags to insert your php code between html tags. For example if you need to print language parameter of URL you can do like this:
<a href="index.php?lang=<?=$lang?>" >A Link</a>
This is equal to this:
<a href="index.php?lang=<?php echo $lang; ?>" >A Link</a>
I'd recommend using a good framework in general, and a templating engine for outputting pages. This way, your data models, your application logic, and your HTML are all kept separate.
This is a somewhat subjective question, but:
echo '<a href="view_users.php?s=' . ($display * ($i - 1)) .
'&p=' . $pages . '&sort=' . $sort . '">' . $i . '</a> ';
This is not very good, because it quickly becomes hard to read. It's the worst option to use IMO.
Here an evolution on how this can be improved:
<a
href="view_users.php?s=<?php echo $display * ($i - 1); ?>&p=<?php echo $pages; ?>&sort=<?php echo $sort; ?>">
<?php echo $i; ?>
</a>
<?php
printf('%i',
$display * ($i - 1), $pages, $sort, $i);
?>
<?php
$q = http_build_query(array(
's' => $display * ($i - 1),
'p' => $pages,
'sort' => $sort
));
?>
<?php echo $i; ?>
<?php
printf('%i',
http_build_query(array(
's' => $display * ($i - 1),
'p' => $pages,
'sort' => $sort
)),
$i);
?>
Paul, what you're looking at in that code is a combination of PHP, CSS and HTML. echo just means print on page and it is a PHP function which is why you see it with the tags.
<?php ?>
Does this answer your question?
Also PHP and HTML and CSS will not parse any whitespace so indenting is done to enhance readability. I suggest you comment your code and format it however it is easier for you to understand. From a professional standpoint check out the W3C validator for proper code formatting.
Both are acceptable really, using echo for short statements and completely breaking out of php for long bits of html. Indentation of your HTML doesn't matter that much, it just looks pretty when someone checks out your source.
wrapping html generation in functions and building output strings can be a good practice. That way you can have complex logic expressed in a readable way:
<?php
function get_pagination_html($pages, $start, $display) {
$html = "";
if ($pages <= 1) return $html;
$current_page = ($start / $display) + 1;
if ($current_page != 1) {
$previous = $start - $display;
$html .= "<div class='pages'><strong><a href='view_users.php?s={$previous}&p={$pages}'> < </a></strong></div>";
}
for ($page_number = 1; $page_number <= $pages; $page_number++) {
if ($page_number == $current_page) {
$html .= "<div class='pages active'><span> {$page_number} </span></div>";
} else {
$page_start = $display * ($page_number - 1);
$html .= "<div class='pages'><strong><a href='iew_users.php?s={$page_start}>&p={$pages}'> {$page_number} </a></strong></div>";
}
}
if ($current_page < $pages) {
$next = $start + $display;
$html .= "<div class='pages'><strong><a href='view_users.php?s={$next}&p={$pages}'> > </a></strong></div>";
}
return $html;
}
echo get_pagination_html($pages, $start, $display);
Notice how much easier it reads. You also don't need any comments because variable names are self explanatory

Making a virtual shelf and populating it via a database

I'm trying to make a virtual shelf type of thing which is populated via a MySQL database. The column shelfPos holds the position of the item on the shelf. Each row/'shelf' starts with <div class="shelfRow"> and obviously ends with </div> so it's styled and positioned correctly. Items on the shelves can be moved around using the jQuery UI droppable interaction.
The overall layout is this: http://jsfiddle.net/aRA5D/
Each shelf can hold 5 items (left to right).
I'm having trouble populating the shelves. At the moment I've got this: (This is in the place of the HTML)
<?php
$sql="SELECT * FROM shelf WHERE userID='$userID'";
$result=mysql_query($sql);
if (mysql_num_rows($result) == 0) {
// Show a message of some sort? (No items)
}
else {
$tries = 1;
$times = 10; // How many shelves. (10 = 2 shelves)
while(($row = mysql_fetch_array($result)) && ($tries <= $times)) {
while ($tries <= $times) {
if ($tries == $row['shelfPos']) {
echo '<div class="drop" id="drop'.$tries.'"><div class="boxArt" id="'.$row['gameID'].'">'.$row['gameID'].'</div></div>';
}
else {
echo '<div class="drop" id="drop'.$tries.'"></div>';
}
$tries = $tries + 1;
}
$times = $times + 5;
}
}
?>
There's several things wrong with it. It doesn't include the <div class="shelfRow"> html (didn't know how/where to put it, as it needs to be echoed after every 5 'blank' and real items - for loop maybe?) and it requires me to input the number of shelves (2 in this case). Would it be possible to determine how many shelves are required based on the item's position? It's awkward to do because it also needs to echo 'blank' .drop divs before and after them so that the items can be moved around.
Hope this all makes sense. Thanks for the help!
First u need to get data in order of ShelfPos
"SELECT * FROM shelf WHERE userID='$userID' order by shelfPos asc"
And try this code:
...
$i = 0;
while($row = mysql_fetch_array($result)) {
//Each 5
if($i % 5 == 0) echo '<div class="shelfRow">';
if ($i == $row['shelfPos']) {
echo '<div class="drop" id="drop'.$i.'"><div class="boxArt" id="'.$row['gameID'].'">'.$row['gameID'].'</div></div>';
}
else {
echo '<div class="drop" id="drop'.$i.'"></div>';
}
//close shelfrow div
if($i % 5 == 4) echo '</div>';
$i++;
}
//to complete the loop
$shelv_left = 5 - ($i % 5);
if($shelv_left < 5) {
for($j=0; $j < $shelv_left; $j++) {
echo '<div class="drop" id="drop'.($i+$j).'"></div>';
}
echo '</div>'; // end shelfrow div
}
...

Categories