How to divide a list of results into pages in PHP

March 9th, 2009

There comes a time when a list of records output by a MySQL query becomes too long to realistically display on a single page, and the programmer wants to break it up into pages. It might be log activity, forum posts or whatever, but the principle is the same – we only want to view a manageable section of the entire record list.

Let’s assume we’re dealing with a set of forum posts in a thread. Your query would take a unique number for the thread ($threadId) and you would pull out a list of posts like this:

<php
 $postSQL="SELECT * FROM posts WHERE (THREAD=$threadId) ORDER BY ID";
 $posts = mysql_query($postSQL) or die(mysql_error());
 while($post=mysql_fetch_array($posts)) {
  // display posts here
 }
?>

This would return all of the posts for this thread in order of creation – ID being the master key for this table.

To split this into pages, we first need to decide how many posts we want per page. Once we have decided on this, we can see how many lines our mysql_query(), above, returns and calculate the number of pages. After that we can decide which page to show and calculate which posts go on that page.

Here’s the altered code:

<?php
 $postSQL="SELECT * FROM posts WHERE (THREAD=$threadId) ORDER BY ID";
 $posts = mysql_query($postSQL) or die(mysql_error());

 $postCount   =mysql_affected_rows();
 $postsPerPage=25;
 $pageCount   =ceil($postCount/$postsPerPage);
 $pageNum     =min(max(1, (int)$_GET['page']), $pageCount);
 $firstPost   =($pageNum-1)*$postsPerPage;
 $lastPost    =min($firstPost+$postsPerPage, $postCount);

 $posts = mysql_query("$postSQL LIMIT $firstPost, $postsPerPage") 
 or die(mysql_error());
 while($post=mysql_fetch_array($posts)) {
  // display posts here
 }
?>

As you can see, we call mysql_query() twice now – the first time to get the total number of posts and the second time to get the subset of those posts once we have decided which ones we want. The highlighted green section shows what has been added, and I’ll go through them here:

$postCount =mysql_affected_rows();

Records the total number of posts returned. We need this so we can calculate how many pages we have in total using…

$postsPerPage=25;

This is how many posts we want on a single page. You can store this in a table for easy altering, or allow it to be overwritten from the URL so that users can decide on their own page sizes.

$pageCount =ceil($postCount/$postsPerPage);

The number of pages is the number of posts divided by the number of posts per page, and rounded up, so ‘30 posts at 25 posts per page’ would return two pages.

$pageNum =min(max(1, (int)$_GET['page']), $pageCount);

Slightly more tricky to read, this line limits the number of the page to be displayed between 1 and the total number of pages, taking into account any page number specified in the URL with ‘&page=’, even if a value is not given.

$firstPost =($pageNum-1)*$postsPerPage;

We need to know the record position – not the ID – of the first post so that we can tell MySQL where to start counting from. This number starts at zero whereas your ID would start at one.

$lastPost =min($firstPost+$postsPerPage, $postCount);

We don’t actually need $lastPost for anything in this example, but it’s nice if you want to display a message along the lines of “Showing posts 25 to 50 of 376″. This value is the actual ID of the last post on the page, so it starts at one and never goes above $postCount.

$posts = mysql_query(“$postSQL LIMIT $firstPost, $postsPerPage”)
or die(mysql_error());

Finally we run your original SQL statement – here held in $postSQL – a second time but with our calculated limits applied.

Calculating Postcodes within a given Radius

August 27th, 2006

So, I was mooching about on t’Internet with ZiKeS this morning, and I remembered that I had wanted to create some kind of Postocode Range Finder using the UK Postcode Database I’d snagged from jibble.org a long, long time ago.

The basic idea was to take a postcode, add a range, and return every postcode within that radius. Initially I was having nightmares about SIN() and COS() functions, but it turns out O-Level maths had some use after all, in the form of Pythagoras’ Triangle Thigummybob, the one that goes ‘The square of the side opposide the right-angle is equal to the sum of squares of the other two sides’. Something like that – we’re reaching into parts of my brain that have gone unused for quite some time here.

I figured I’d let the server do all the work, and the final SQL I came up with was:

    SELECT POSTCODE,GRIDREFX,GRIDREFY FROM ukpostcodes
    WHERE SQRT(
    POW(ABS($xpos-GRIDREFX),2) +
    POW(ABS($ypos-GRIDREFY),2)
    ) < $dist

$dist being the range required in metres and $xpos and $xpos being the Grid Ref X and Y thingies respectively from my ‘root’ postcode. The script seems to work, and returns the other postcodes within my specified range, though in no particular order. I guess ‘nearest first’ would be cool.

My next problem is to actually apply this to something, since I don’t actually have a project in mind for it. Initially I thought of something like Dating or maybe Car/House sales, or even an entire community thing which would let you see exactly what was available in your area. Stay tuned, folks – anything could happen in the next half hour few months.

UK Postcode Database and Calculating Distances Between Postcodes

February 15th, 2006

Looking over the website counter area I’ve noticed an increasing number of people are searching for information on how to calculate the distance between two postcodes. My original post on the matter sent people off in the direction of jibble.org but I’ve had at least one person mention that the uk postcode database isn’t available anymore.

For that reason I’ve uploaded the UK Postcode Database (with grid references) to my NTL space, here:

    UK Postocode Database
    I’ve removed the link above since the legal status was questionable.  A fully legal, open version of the postcode database can be found at New Popular Edition Maps.

Have a look at the page on jibble (link above) for further information.

Original Post

    Currently I am mucking about with postcodes, converting them to coordinates that I can plonk onto a map of the UK, and maybe thereafter use to calculate straight-line distances between two codes. Lucky for me (yay me!) I found a free, plain-text database on jibble.org that already had the coords as metres – saving me 90% of the work I originally envisaged converting Grid References.

    I’m plonking them into a simple MySQL table at the mo, then I’ll be able to get the positions by searching on the first half of someone’s postcode. It’s not accurate down to street level but it’s fine for someone looking the length of the country. The next stage will be to write a function that takes into account the size of my bitmap image of the UK, complete with various pixel offsets, and returns an X or Y position in pixels representing the location of that postcode. I don’t forsee any problems.

(Hopefully Google wil link to this page from now on…)