By: Kevin
Introduction
This Tutorial will show you an example of a more efficient pagination method than those commonly used on small web sites. Although the query does run on every new page view, it ONLY returns the rows needed for the current page. Another great thing about this method is that the url variable to go to any page is simply the page number that you want to go to.

Download the CFML Code Here
Download the SQL for the Sample Database Here
A Working Example


Requirements
Cold Fusion 5, 6, or 7 (tested on 6 and 7)
MySQL (tested with version 4.0x and 4.1x)


Set Up Variables
A few variables are required to run this script:

The default page is always the first page. If no page number is specified, then page 1 will be shown

<cfparam name="url.page" default="1">


Here we set how many page number links will be shown at one time. If there are 100 pages of records, we probably do not want 100 page links running across the screen.

<cfset page_links_shown = 5>


How many records do we want on each page? I will set this to 5 for this tutorial. 1 to n is acceptable. Choosing how many records per page depends on your web site and how you want it to look and feel.

<cfset records_per_page = 5>


The variable start_record will tell MySQL the first record we want to get. Take the start page (let's say we are viewing page three) 3, multiply by records_ per_page (we set that to 5) and minus records_per_page (5) That leaves us with 3 * 5 - 5 = 10. Now we know the first row that we need (start_record) should be 10.

<cfset start_record = url.page * records_per_page - records_per_page>


The Queries...
The database that this tutorial uses is extremely simple. It has an 'id' field and a 'names' field. We will pull out the names to display.

This Query will give us the total number of records available. We will us the result of this later.

<cfquery name="get_count" datasource="#dsn#">
   SELECT COUNT(id) AS records FROM pages_names
</cfquery>


This Query will get the actual records for the page to display. This query actually has the secret to this whole tutorial. The MySQL LIMIT function. We tell it what row to start on, and how many rows after that to get. Simply plug in our variables start_record and records_per_page.

<cfquery name="get_names" datasource="#dsn#" result="get_data">
   SELECT names
   FROM pages_names
   ORDER BY names
   LIMIT #start_record#, #records_per_page#
</cfquery>


The Page Links...
The page links can come in many different varieties. I will show a few basic ones here, and a neat way to keep the page number links under control so they don't spread across the screen when there are a LOT of pages

Each of the Following section can be used separately or put in a different order. (previous / next links, first / last links, and the pages index)

First we will set up a few more variables that some of these page link examples will use.

Variable total_pages finds out how many pages total there will be by simply calculating the records per page and total records that we got earlier.

<cfset total_pages = ceiling(get_count.records / records_per_page)>


And let's start up our cfoutput so our variables can be used on screen.

<cfoutput>


We will output the query first. Remember, page one is default.

<cfloop query="get_names">
   #start_record + currentrow#. #names#<br/>
</cfloop>
<hr>


Previous Page Link:
The previous page link is dead simple. If the current page does not equal 1, then the previous page = current page minus 1. If the current page = 1, then show the text only, no link.

<cfif url.page EQ 1>
   Prev Page
<cfelse>
   <a href="pages.cfm?page=#url.page-1#">Prev Page</a>
</cfif>
<hr>


Next Page Link:
Next link is just as simple. If the current page multiplied by the records_per_page variable is Less than the total number of records, then there must be a next page, so show the link. Otherwise, show the text only.

<cfif url.page * records_per_page LT get_count.records>
   <a href="pages.cfm?page=#url.page+1#">Next Page</a>
<cfelse>
   Next Page
</cfif>
<hr>


Page Numbers Links Index:
Page number links are a little trickier, and can be done several ways. Here is a method I like. We need to set a few more variables if we are going to use this method. We need to know how many page links to display at one time. If there are too many page links on the screen, it can look bad. Imaging the numbers 1 through 100 on the screen on every page.

start_page is the default page to start showing links to. This is different than the default page of records to show. This variable only applies to the first page that we want to link to, and by default, it must be 1.

<cfparam name="start_page" default="1">


show_pages will determine how many page links to show at a time. We said 5 for this tutorial, but 10 or 15 is on too. If there are not enough records to fill the default, we will later set this to a lower number.

<cfparam name="show_pages" default="#min(page_links_shown,total_pages)#">


Now this next bit of code simply makes sure that our current page link is listed in the currently displayed page links index, since we are not showing every page link at a time. This code will 'roll' through the page links. This will make more sense in the working example. So if we have 10 pages, and at first we show links to pages 1,2,3,4,5 and click on page 5, when the page reloads, we will have links to pages 3,4,5,6,7 showing. You can dissect the code if you wish, but thats what it does. It gives us a value for start_page that will be used in the loop that write the page links out in the next step.
<cfif url.page + int(show_pages / 2) - 1 GTE total_pages>
   <cfset start_page = total_pages - show_pages + 1>
<cfelseif url.page + 1 GT show_pages>
   <cfset start_page = url.page - int(show_pages / 2)>
</cfif>


We need to set an end page for our page links to this is simply our start_page + show_pages variable that we set earlier minus 1.

<cfset end_page = start_page + show_pages - 1>


Now that we have a start_page and end_page variable, we'll loop from one to the other. We do a quick check that if the current page equals the page link we are writing, then don't make a link. The cfif within this loop is optional, but the loop and the output of the a href is required.

<cfloop from="#start_page#" to="#end_page#" index="i">
    <cfif url.page EQ i>
       #i#
   <cfelse>
       <a href="pages.cfm?page=#i#">#i#</a>
    </cfif>
</cfloop>
<hr>


First Page Link:
First Page / Last Page links are as easy as previous / next. First page ALWAYS is page 1.

 <a href="pages.cfm?page=1">First Page</a>
<hr>


Last Page Link:
Last page is ALWAYS the total_pages variable that we set earlier! That simple.
 <a href="pages.cfm?page=#total_pages#">Last Page</a>
<hr>


Finish the cfoutput

</cfoutput>


Optional features
· You may want to use the int() function on your outputs of page numbers in case some goober types a decimal into the url page= variable. This way, it will still work, but show whole numbers instead of decimal numbers for page links.

· Check for non-numerical url.page values. For the simplicity of this tutorial, I did not. This code will throw an error if url.page is a non-numeric value.

· You can also add a more complex page link index that has a (next 10) and (previous 10) pages option. Do what you choose, and whatever fits your layout and data the best.

CFDump To see your query results, query execution time, etc...
<cfdump var="#get_names#">
<cfdump var="#get_data#">

About This Tutorial
Author: Kevin
Skill Level: Beginner 
 
 
 
Platforms Tested: CF5,CFMX,CFMX7
Total Views: 61,094
Submission Date: October 14, 2005
Last Update Date: June 05, 2009
All Tutorials By This Autor: 3
Discuss This Tutorial
  • No thanks. As a tutorial, you should understand what the code is doing, then implement it on your own. This site is NOT for copy and paste free scripts that teach you nothing. Anyways, hope you enjoy and that the tutorial was helpful. Thanks

  • With good indexes you can even sort by a few rows and still be quick this way.

  • Please give all the code in all file Here it is given seperately

  • I agree, there are many ways to go about this. Caching a query is simply not possible in some situations where data must be fresh - even a minute or two matters sometimes. Some content management systems can run 50 or more queries just to build a page.This method is just an easily implemented way to make simple pagination on medium size databases... With good indexes you can even sort by a few rows and still be quick this way. This is not a one size fits all solution. For people that are actually looking for a solution for a web site or small application that needs fresh data, this works well.

  • see all link a href="index.cfm?showAll=yes" then in the code SELECT names FROM pages_names ORDER BY names LIMIT #start_record#, #records_per_page#

  • Great stuff. Took me a few to understand... But really helps me when I have a table with 10,000 rows. Thanks for this!

  • Can you show what you would add in the code for a "See All" link?

  • I can't remember if I answered this on my website or email already or not... you would put the script anywhere that the form submitted. a self submitting form would probably require a cfif around the query and cfoutput sections to check if the form was submitted put cfquer and output query here to 'remember' a search phrase I generally append it to all the page number urls and insert that url var back into the query to search for the same thing - but get the next page results if a new page was clicked on. hope that helps - might be too late though.

  • Kevin, You are running two queries on each page. And with every page there is that overhead of sending and receiving query. There is a better way to do the same. 1. use cfquery with cachedwithin 2. use query of queries to do the work for you. You will have to use the cached within properly. Query of queries will let you page without sending datasets back and forth, AND you can add criteria and sorting so you can search within results. How about that !! Anang

  • This was the easiest method to follow so far to create pagination on the results of a coldFusion query. My question is since I'm using a self-posting form, can you provide an example of where this code would be placed within a that form? Also, as you go through each page, how can I ensure that the user will be able to see what he queried? For example, if I use a text box submission, how will the user remember on page 7 what he orginially queried? Thanks.

Advertisement

Sponsored By...
Powered By...