TalkPHP

TalkPHP (http://www.talkphp.com/forums.php)
-   Script Giveaway (http://www.talkphp.com/script-giveaway/)
-   -   Pagination Function (http://www.talkphp.com/script-giveaway/4144-pagination-function.html)

allworknoplay 04-16-2009 02:00 PM

Pagination Function
 
Hey guys, here's the pagination function that I've been working on. It is based off of Websavvy's pagination program so I don't want to take full credit for it. Everything works as I want to except one feature and I will explain that later. But here's the code.


Code:

/* GET CURRENT PAGE */
$get_page = $_GET['p'];
/* SET PAGE LIMIT TO 25 FOR CURRENT TESTING */
$page_limit = "25";

/* QUERY TO GET TOTAL NUMBER OF ENTRIES FOR PAGINATE FUNCTION */
$query_total = "SELECT * FROM schedules";


function pagination($get_page,$display,$query_total,$page_limit) {
                       
/* SET SOME VARIABLES */
if(!$get_page) $p = 1;
if(!$display) $display = 5;
$page_next = ($get_page + 1);
$page_prev = ($get_page - 1);
                               
                               
/* GET TOTAL NUMBER OF ENTRIES FIRST */
$results = mysql_query($query_total);
$totalrows = mysql_num_rows($results);

/* CALCULATE LAST PAGE LINK */
$page_last = ceil($totalrows/$page_limit);
       
/* USE $start VAR FOR DATABASE QUERY ex: LIMIT $start,$page_limit */
$start = ($get_page - 1) * $page_limit;
                               
$starting_no = $start + 1;

if (($totalrows - $start) < $page_limit) {
        $end_count = $totalrows;
        } elseif ($totalrows - $start >= $page_limit) {
        $end_count = $start + $page_limit;
        }
                               
                               
/* CREATE PAGES TO DISPLAY */
for ($i=1; $i<=$page_last; $i++) {
                                       
if ($i != $get_page) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
else $display_pages[] = " $i";
                                       
}
                               
                               
/* IF ON PAGE 1, UNLINK FIRST AND PREV LINKS */
if($get_page == 1) {
$first = "First";
$prev = "Prev";
        }else{
$first = "<a href=\"$_SERVER[PHP_SELF]?p=1\">First</a>";
$prev = "<a href=\"$_SERVER[PHP_SELF]?p=$page_prev\">Prev</a>";
        }
                               
/* IF ON LAST PAGE, UNLINK LAST AND NEXT LINKS */
if($get_page == $page_last) {
        $last = "Last";               
        $next = "Next";
        }else{
$last = "<a href=\"$_SERVER[PHP_SELF]?p=$page_last\">Last</a>";               
$next = "<a href=\"$_SERVER[PHP_SELF]?p=$page_next\">Next</a>";                               
        }
                               
return (array($first,$prev,$display_pages,$next,$last,$totalrows,$starting_no,$start,$page_limit,$end_count));
                       
        }###END FUNCTION
                       
list($first,$prev,$display_pages,$next,$last,$totalrows,$starting_no,$start,$page_limit,$end_count) = pagination($_GET[p],5,$query_total,$page_limit);

echo "<span class=\"style13\">" . "$first | $prev" . implode(' ',$display_pages) . " $next | $last" . "</span>";

Code:

OUTPUT YOUR RECORDS: SECOND QUERY USING LIMIT

$query2 = "SELECT * FROM schedules LIMIT $start,$page_limit";
$result2 = mysql_query($query2);

etc etc etc......



Ok, so here is what the output is:

First | Prev 1 2 3 4 Next | Last

and

Viewing Items (1 - 25 of 76 Entries)



Everything works pretty well. When you are on the first page,
the "First" and "Prev" gets unlinked since there's no need to click on them. If you are on the last page, the same thing happens for the "Next" and "Last" links..

There is only one issue that I have, and that is the "1 2 3 4" part. That is based on how many entries are in the table divided by how many items to list per page.

Anyways, if you have a lot of entries, say 1,000. You will get too many links like this: "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ....etc".

What I would like to do is keep it "clean". Displaying only 5 at a time with the "current" page in the middle:

So say you are on page 3. It would look like this.

First | Prev 1 2 3 4 5 Next | Last


If you're on page 7. It would look like this.

First | Prev 5 6 7 8 9 Next | Last


If anyone has "hints" please let me know, it's one of those things that you can either figure out in 5 minutes or it takes a day...I don't think it's hard, just a matter of "figuring" it out...but I know there are a lot of people here with "pagination" experience.

Also, PLEASE comment on my code, if you have suggestions to make it better, let me know, I won't be offended...

Just don't tell me to do it in OO because I'm still new to that and that will be my next project...

Tanax 04-16-2009 04:00 PM

First off, why are you posting this in Script Giveaways if you need help with it?
Secondly, I see you still base your entire function on a database - which is fine - but not really good practice.

About your issue, you have to insert a new variable $span, and do some simple math logic to get around this. I would post my updated script, but it's entirely OOP so I'm not sure if that would actually do any help.

But like I said, you need to do some simple math.
Bascicly, what you wanna check for is if the pagenr(in your for-loop) is outside the span, and only display those who are in the span. By span, I mean the value of the variable $span, which would be an integer - corresponding to how many pages you want on each side of the current page.

Example: $span = 2
3 4 5 6 7

$span = 4
1 2 3 4 5 6 7 8 9

Here's the code to display the first link if the you're outside the span and above first page.
PHP Code:

// If the current page minus the span is larger than 1, it means that the first page is outside the span, and thus we want to
    // display it!
    
if(($page[0] - $span) > 1) {
                
        echo 
'<a href="?page=1">First</a> ';
        
        
// If the current page minus (span + 1) is larger than 1, it means that the first page is outside the span AND it is outside the
        // span with more than 1, and thus we want to add an extra ".." after the first link.
        
if(($page[0] - ($span 1)) > 1) {
                
            
$firstlink .= '.. ';
                
        }
                
    } 

$page[0] is the current pagenr.

allworknoplay 04-16-2009 04:59 PM

Quote:

Originally Posted by Tanax (Post 23117)
First off, why are you posting this in Script Giveaways if you need help with it?

Yeah, I figured I would share what I have so far. I suppose I should have waited until the code is 100% complete to my liking.

Quote:

Originally Posted by Tanax (Post 23117)
Secondly, I see you still base your entire function on a database - which is fine - but not really good practice.

Well I think this is POV, I'd like to get suggestions from others. I know good practice is to be as general as possible with the data so you can insert any type, (arrays, SQL, files/directories etc..) But you also have to remember I am a newbie...

Quote:

Originally Posted by Tanax (Post 23117)
About your issue, you have to insert a new variable $span, and do some simple math logic to get around this. I would post my updated script, but it's entirely OOP so I'm not sure if that would actually do any help.

But like I said, you need to do some simple math.
Bascicly, what you wanna check for is if the pagenr(in your for-loop) is outside the span, and only display those who are in the span. By span, I mean the value of the variable $span, which would be an integer - corresponding to how many pages you want on each side of the current page.

Example: $span = 2
3 4 5 6 7

$span = 4
1 2 3 4 5 6 7 8 9

Here's the code to display the first link if the you're outside the span and above first page.
PHP Code:

// If the current page minus the span is larger than 1, it means that the first page is outside the span, and thus we want to
    // display it!
    
if(($page[0] - $span) > 1) {
                
        echo 
'<a href="?page=1">First</a> ';
        
        
// If the current page minus (span + 1) is larger than 1, it means that the first page is outside the span AND it is outside the
        // span with more than 1, and thus we want to add an extra ".." after the first link.
        
if(($page[0] - ($span 1)) > 1) {
                
            
$firstlink .= '.. ';
                
        }
                
    } 

$page[0] is the current pagenr.



Thank you! I think I can figure it out now with "$span".
Let me get back to the grind and hopefully figure it out at some point today...

Tanax 04-16-2009 09:20 PM

Quote:

Originally Posted by allworknoplay (Post 23118)
Well I think this is POV, I'd like to get suggestions from others. I know good practice is to be as general as possible with the data so you can insert any type, (arrays, SQL, files/directories etc..) But you also have to remember I am a newbie...

Thank you! I think I can figure it out now with "$span".
Let me get back to the grind and hopefully figure it out at some point today...

What does POV mean? Yes of course, but remember - it's when you're a "newbie" that you learn the most, and if you practice the "wrong" way of stuff, you will have to struggle more to "unlearn" the "wrong" way, and learn the right way - if that makes any sense?

Post the progress you make!

allworknoplay 04-17-2009 04:41 PM

Ok, I have figured out the span issue. Here is how I am doing it.

As it loops through, it looks at the $get_page variable, and appends 2 pages before and after it and puts it into an array.

I've tested it and it works perfectly!

Code:

/* CREATE PAGES TO DISPLAY */
for ($i=1; $i<=$page_last; $i++) {
                                       
                                       
if(($get_page - 2) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if(($get_page - 1) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if($get_page == $i) $display_pages[] = "$i";
if(($get_page + 1) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if(($get_page + 2) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";

        }

If $get_page = 10.

Then the output will be:

8 9 10 11 12

allworknoplay 04-17-2009 04:44 PM

Quote:

Originally Posted by Tanax (Post 23126)
What does POV mean? Yes of course, but remember - it's when you're a "newbie" that you learn the most, and if you practice the "wrong" way of stuff, you will have to struggle more to "unlearn" the "wrong" way, and learn the right way - if that makes any sense?

Post the progress you make!


yes that makes sense. I definitley want to start off with the correct fundamentals because the last 10 years I've been hacking my way through programs.

The only issue is, I don't know of any other way of getting data other than using mySQL. What I mean by that is, if you were to tell me 2 or 3 other ways in which other people are getting data not using SQL, then I can look into making the function accept more generic attributes when calling the function so it would be more independent of databases....

POV = point of view

Take a look at my code I just posted that will span 2 elements to the right and left of the current page.

I'm positive that's not what you had in mind so if you have a better way, please let me know.

Of course with programming there are always 100 different ways to do things...but I would like your comments on my approach...

Salathe 04-17-2009 06:01 PM

More ways of using MySQL other than the basic MySQL extension:
  1. MySQL Improved
  2. PDO MySQL

More data stores other than MySQL:
Then there might be a time where you want to paginate something else entirely like existing PHP data (arrays, objects). In basic terms, pagination should be able to take a collection of things and break it down into paged sets. Those things needn't necessarily be database query results and the output needn't necessarily be HTML (or the exact HTML that your function uses).

allworknoplay 04-17-2009 06:12 PM

Quote:

Originally Posted by Salathe (Post 23151)
In basic terms, pagination should be able to take a collection of things and break it down into paged sets. Those things needn't necessarily be database query results and the output needn't necessarily be HTML (or the exact HTML that your function uses).

Ohhh ok, that makes more sense. See, I always thought pagination was just your everyday navigation of HTML pages. I didn't know that it was more of an all around method of "flipping" through things....

That's why I couldn't see beyond using DB queries to build the navigation pages...

I have heard of mysqli, and PDO but never really looked into them, I'll take a peek now...

allworknoplay 04-17-2009 06:51 PM

Ok, I modified my function so that the DB query isn't within it. Now you have to do the DB query outside, then provide the results to the function. This SHOULD work for other types of data types correct?

You should be able to feed it results from other DB sources or feed it an array and it should still work....


Code:

/* QUERY TO GET TOTAL NUMBER OF ENTRIES FOR PAGINATE FUNCTION */
$query_total = "YOUR SELECT STATEMENT";
       
/* GET TOTAL NUMBER OF ENTRIES FIRST */
$results = mysql_query($query_total);
$totalrows = mysql_num_rows($results);


function pagination($get_page,$totalrows,$page_limit) {
                       
/* SET SOME VARIABLES */
if(!$get_page) $p = 1;
if(!$display) $display = 5;
$page_next = ($get_page + 1);
$page_prev = ($get_page - 1);

/* CALCULATE LAST PAGE LINK */
/* THIS ALSO WILL BE USED IN THE FOR LOOP */
$page_last = ceil($totalrows/$page_limit);
       
/* USE $start VAR FOR DATABASE QUERY ex: LIMIT $start,$page_limit */
if($p == 1)        $start = 0;
else        $start = ($get_page - 1) * $page_limit;
                               
/* CREATE OFFSET ex: 1 -25, 26 - 50 */
$starting_no = ($start +1);

/* CREATE ENDCOUNT ex: 1 - 25, THE 25 IS THE ENDCOUNT */
if (($totalrows - $start) < $page_limit) {
$end_count = $totalrows;
} elseif ($totalrows - $start >= $page_limit) {
$end_count = $start + $page_limit;
}

/* CREATE PAGES TO DISPLAY */
for ($i=1; $i<=$page_last; $i++) {
                                       
                                       
if(($get_page - 2) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if(($get_page - 1) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if($get_page == $i) $display_pages[] = "$i";
if(($get_page + 1) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if(($get_page + 2) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";

}
                               
                               
/* IF ON PAGE 1, UNLINK FIRST AND PREV LINKS */
if($get_page == 1) {
$first = "First";
$prev = "Prev";
}else{
$first = "<a href=\"$_SERVER[PHP_SELF]?p=1\">First</a>";
$prev = "<a href=\"$_SERVER[PHP_SELF]?p=$page_prev\">Prev</a>";
}
                               
/* IF ON LAST PAGE, UNLINK LAST AND NEXT LINKS */
if($get_page == $page_last) {
$last = "Last";               
$next = "Next";
}else{
$last = "<a href=\"$_SERVER[PHP_SELF]?p=$page_last\">Last</a>";               
$next = "<a href=\"$_SERVER[PHP_SELF]?p=$page_next\">Next</a>";                               
}
                               
return (array($first,$prev,$display_pages,$next,$last,$totalrows,$starting_no,$start,$page_limit,$end_count));
                       
}###END FUNCTION
                       
list($first,$prev,$display_pages,$next,$last,$totalrows,$starting_no,$start,$page_limit,$end_count) = pagination($_GET[p],$totalrows,$page_limit);


Tanax 04-17-2009 07:06 PM

Quote:

Originally Posted by allworknoplay (Post 23153)
Ok, I modified my function so that the DB query isn't within it. Now you have to do the DB query outside, then provide the results to the function. This SHOULD work for other types of data types correct?

You should be able to feed it results from other DB sources or feed it an array and it should still work....


Code:

/* QUERY TO GET TOTAL NUMBER OF ENTRIES FOR PAGINATE FUNCTION */
$query_total = "YOUR SELECT STATEMENT";
       
/* GET TOTAL NUMBER OF ENTRIES FIRST */
$results = mysql_query($query_total);
$totalrows = mysql_num_rows($results);


function pagination($get_page,$totalrows,$page_limit) {
                       
/* SET SOME VARIABLES */
if(!$get_page) $p = 1;
if(!$display) $display = 5;
$page_next = ($get_page + 1);
$page_prev = ($get_page - 1);

/* CALCULATE LAST PAGE LINK */
/* THIS ALSO WILL BE USED IN THE FOR LOOP */
$page_last = ceil($totalrows/$page_limit);
       
/* USE $start VAR FOR DATABASE QUERY ex: LIMIT $start,$page_limit */
if($p == 1)        $start = 0;
else        $start = ($get_page - 1) * $page_limit;
                               
/* CREATE OFFSET ex: 1 -25, 26 - 50 */
$starting_no = ($start +1);

/* CREATE ENDCOUNT ex: 1 - 25, THE 25 IS THE ENDCOUNT */
if (($totalrows - $start) < $page_limit) {
$end_count = $totalrows;
} elseif ($totalrows - $start >= $page_limit) {
$end_count = $start + $page_limit;
}

/* CREATE PAGES TO DISPLAY */
for ($i=1; $i<=$page_last; $i++) {
                                       
                                       
if(($get_page - 2) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if(($get_page - 1) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if($get_page == $i) $display_pages[] = "$i";
if(($get_page + 1) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";
if(($get_page + 2) == $i) $display_pages[] = " <a href=\"$_SERVER[PHP_SELF]?p=$i\">$i</a>";

}
                               
                               
/* IF ON PAGE 1, UNLINK FIRST AND PREV LINKS */
if($get_page == 1) {
$first = "First";
$prev = "Prev";
}else{
$first = "<a href=\"$_SERVER[PHP_SELF]?p=1\">First</a>";
$prev = "<a href=\"$_SERVER[PHP_SELF]?p=$page_prev\">Prev</a>";
}
                               
/* IF ON LAST PAGE, UNLINK LAST AND NEXT LINKS */
if($get_page == $page_last) {
$last = "Last";               
$next = "Next";
}else{
$last = "<a href=\"$_SERVER[PHP_SELF]?p=$page_last\">Last</a>";               
$next = "<a href=\"$_SERVER[PHP_SELF]?p=$page_next\">Next</a>";                               
}
                               
return (array($first,$prev,$display_pages,$next,$last,$totalrows,$starting_no,$start,$page_limit,$end_count));
                       
}###END FUNCTION
                       
list($first,$prev,$display_pages,$next,$last,$totalrows,$starting_no,$start,$page_limit,$end_count) = pagination($_GET[p],$totalrows,$page_limit);


Ah, much better :-)
Now go learn OOP and build a class off of it ;-) ^^

allworknoplay 04-17-2009 07:08 PM

Quote:

Originally Posted by Tanax (Post 23154)
Ah, much better :-)
Now go learn OOP and build a class off of it ;-) ^^


Thanks, I should be able to just take this function and convert it into OO.

I will try it out now, I know I will need your help, Salathe and anyone else that is around lately....

Of course I'll try to do it on my own AND I won't post it here until it's complete. :-P

BTW: I printed out your pagination class, hopefully I can pick up some tips from it without copying it too much...

Tanax 04-17-2009 07:39 PM

Just a tip, don't print anything in your class, only return values - never echo them out

allworknoplay 04-17-2009 07:45 PM

Quote:

Originally Posted by Tanax (Post 23156)
Just a tip, don't print anything in your class, only return values - never echo them out

Good to know, thanks!

I am having a hard time transitioning the mental thought from procedural code to OO code...

I hope I can have enough done later today for you to take a look....

Kalle 04-17-2009 08:51 PM

Just a little security tip; Remember to escape HTML characters when using $_SERVER['PHP_SELF'], as its not filtered and may contain input that can cause XSS

allworknoplay 04-17-2009 08:55 PM

Quote:

Originally Posted by Kalle (Post 23158)
Just a little security tip; Remember to escape HTML characters when using $_SERVER['PHP_SELF'], as its not filtered and may contain input that can cause XSS

hmmm, I know how to escape user input with mysql_real_escape function, how do you escape $_SERVER['PHP_SELF']?

Is it with the mysql function too or is there a PHP function?

Tanax 04-17-2009 09:00 PM

I think he's referring to this:
PHP Code:

htmlspecialchars($data);
//or perhaps this:
urlencode($data); 


allworknoplay 04-17-2009 09:03 PM

Quote:

Originally Posted by Tanax (Post 23160)
I think he's referring to this:
PHP Code:

htmlspecialchars($data);
//or perhaps this:
urlencode($data); 



Ok so I should do this?

$current_page = htmlspecialchars($_SERVER['PHP_SELF']);

Also, I was just thinking, what if we were to define the PHP_SELF like this:

define(CURRENT_PAGE,$_SERVER['PHP_SELF']);

Is that not a good idea?

Kalle 04-17-2009 10:55 PM

yes escape $_SERVER['PHP_SELF'] like: $_SERVER['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES);

=)

allworknoplay 04-17-2009 10:59 PM

Quote:

Originally Posted by Kalle (Post 23168)
yes escape $_SERVER['PHP_SELF'] like: $_SERVER['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES);

=)


ahhh! thanks!

Quick question, how would I use this in a class?

In the HTML, I would do it the way you just wrote it:

$_SERVER['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES);


But when including a class, do I have to do the same thing in the class?

$_SERVER['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES);

Reason why I ask this is that in my class I am using $_SERVER['PHP_SELF'] so I want to make sure that is escaped too...

Kalle 04-17-2009 11:32 PM

$_SERVER is a superglobal, that means when you update a value it will reflect all scopes:

PHP Code:

<?php
    expose_phpself
();
    
$_SERVER['PHP_SELF'] = '/this/is/a/custom/value';
    
expose_phpself();

    function 
expose_phpself()
    {
        echo(
$_SERVER['PHP_SELF'] . PHP_EOL);
    }
?>

(as if I understood your question correctly :))


All times are GMT. The time now is 03:21 AM.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0