views:

266

answers:

5

I'm new to programming and have a question about navigation. What are the various methods that can achieve a "First", "Previous", "Next" and "Last" navigation, as seen in article or comic based sites? (Admittedly the "First" link isn't confusing as it can stay static, but what about the others?) For example, on the 50th page, the links would appropriately lead to the 49th and 51st (if it exists, if not it would not function but would automatically become active when such a page exists. In most examples of this I see urls ending with something like ".php?id=50" but am not certain how it's achieved, with a database? Any help will be very much appreciated, thanks.

+1  A: 

Perhaps this tutorial or this one will help you.

Edit: meh, the first one was a highly annoying site. Found another. :)

ghoppe
+1  A: 

I am assuming you are not talking about pagination (i.e. splitting a big list of records into multiple pages) but about having a detail view of a record, and preoviding "next" / "previous" links to the next and previous record.

If you have no fixed way of finding out the previous and last neighbours (so you can't just say "current ID -1" and "+1") you will have to do a database query ordered by your criteria, and find out the previous and next members.

Maybe it's to deeply into the issue, and not what you need to start out, but I asked a question recently that concerns optimization issues and differnt approaches to do this "neghbor lookup" in a fast and efficient way. Caching the results of a “next” / “previous element” query

Pekka
+1  A: 

Theres quite a few methods to go about doing this, ranging from complex to simple. (Seach for php pagination on google).

The ?id=50 in some urls is to determine the item to start at.

For example in sql, you determine a range of items to select using SELECT * FROM tbl LIMIT 0,10 , This will select records 0-10. then SELECT * FROM tbl LIMIT 11,10 would select 11 to 20.

cast01
Actually, `LIMIT 11, 20` would select records 11-30, as the second parameter in `LIMIT` is the duration, not the end point.
Tatu Ulmanen
Yeah well spotted, just made a typo there, edited now :)
cast01
+1  A: 

This kind of navigation is called pagination. There are three variables that affect pagination on a given page:

  • The total number of items
  • The number of items per page
  • Current page

You usually can get the total number of items from a database easily, using a query like this:

$query = "SELECT COUNT(*) FROM tbl";
$count = mysql_result($query, 0);

And as you know the number of items per page and the current page, you can figure out how many pages are in total:

$perpage = 10; // This you can define yourself

$pages_count  = ceil($count / $perpage);

After that, it's easy to do some simple if clauses to see what kind of navigation should be displayed:

// Get the current page or set default if not given
$page = isset($_GET['page']) ? $_GET['page'] : 1;

$pages_count = ceil($count / $perpage);

$is_first = $page == 1;
$is_last  = $page == $pages_count;

// Prev cannot be less than one
$prev = max(1, $page - 1);
// Next cannot be larger than $pages_count
$next = min($pages_count , $page + 1);

// If we are on page 2 or higher
if(!$is_first) {
    echo '<a href="index.php?page=1">First</a>';
    echo '<a href="index.php?page='.$prev.'">Previous</a>';
}

echo '<span>Page '.$page.' / '.$pages_count.'</span>';

// If we are not at the last page
if(!$is_last) {
    echo '<a href="index.php?page='.$next.'">Next</a>';
    echo '<a href="index.php?page='.$pages_count.'">Last</a>';
}

To select the correct results from a database for the given page, you can use a query like this:

$query = "SELECT * FROM tbl LIMIT ".(int)($page - 1)." ".(int)$perpage;

That's really all there's into it. Hope this helps.

Tatu Ulmanen
+2  A: 

The bit at the end of the URL is called a GET variable. When a user goes to a page with one at the end, for example:

example.org/comics/myawesomecomic.php?page=50

The server goes to that page and (usually) a server-side script will do some work before outputting the page to the user. With PHP, the GET variable is a Global Variable (along with others, the big ones being POST and COOKIE), that the php script can retrieve by getting the value passed from the server to script, in this case in $_GET['page'].

So assuming you have a script that handles all requests for the comic storyline "My Awesome Comic" and it's broken up into 60 pages, all a user has to do to get to any page is change the GET variable to the page number. Your script might do something really simple, like get the contents of a directory called myawesomecomic/ and grab a file called 50.html and then output it to the user. But chances are, you want something a tad more sophisticated since you went to this trouble, so instead it goes and grabs page 50 from a database and updates all of the navigation and maybe even throws a stylish 50 - 60 in the top corner.

Now, here's the easy part, aka the answer to your question. Now that you know how GET variables work and what the server-script does with them, all you have to do to make navigation like you describe is:

$current_page = $_GET['page'];
$next_page = $current_page + 1;
$prev_page = $current_page - 1;
$first_page = 1;
$last_page = 

And that last part is going to be up to you to know already. Either you can always have the same number of pages, or you can query the DB at the same time you pull up the current page, etc. Let's say you did query the DB for the total page count while you were getting the current page. And it returned 60 (and we'll assume, just to avoid headaches that 60 is the page count starting from 1, not 0), so back to the navigation...

$last_page = 60;

Now you have your first, last, prev, and next. Assuming you know your way around HTML, all that's left (besides making this look pretty) is: echo " First Page Previous Page Next Page Last Page ";

And there's your navigation. Obviously you'll want to arrange them to fit your site, not have them run together like that, use cool arrows, etc. But the links will work even if you don't do anything fancy.

BUT!

I just gave you the really nice, my first time having fun with PHP version. Things I left out (that you should ask more about or do some serious research on):

  • Since GET Variables are including on the URL, they aren't hard to figure out. I could easily change ?page=50 to ?page=1=1 and, depending on how you are getting the content, I may have just asked for all contents of your database. Never grab user-input (even the URL) straight into your variables. If you know it's page number, then you know it's a number. Check the input to make sure it's a number before running it through your script and your database.

  • You need to have a system for if the user puts in a number and it's out of range. Something simple like "Sorry, page not found" or even "Page not found, starting at the beginning" and sending them back to page 1, whatever. If you just output nothing, it looks bad and you reveal parts of your script's logic that could be manipulated.

  • When you get comfortable with GET variables, I suggest ditching them for mod_rewrite (assuming you are on an apache server). Don't jump in now, but when you get the hang of it, you can start making URLs like: example.org/comics/myawesomecomic/page50 or example.org/comics/myawesomecomic/page/50 or what have you. What really happens is all pages in that directory get redirected to the same script which then checks the URL's ending to figure out what to pull from the DB. But to the end-user, it looks like there's just a webpage. This looks cleaner (I think) and does even more to cover your script's logic. But I'm saying to wait on it because it also opens you up for other risks that can be harder to anticipate until you're used to sanitizing your user-input and handling standard page errors like "page not found."

Anyways, figuring out stuff like adding a week to a current date and adding a page number to the current page is totally how I got into PHP and web app development, so I hope this was helpful and straightforward.

Anthony
This is a really great answer, will bookmark it for future askers, but what if I'm in record 31 and record 30 was deleted? You would have to do some checks for that, I would at least mention that.
Pekka