0

Lately I've been messing around with a ColdFusion forum script, and I'm trying to add pagination to it so that it only displays 10 comments per page instead of all of them. Sadly, I've only found complicated solutions to do this and no simple solution like I was used to in PHP. Currently, this is my code for getting the comments out of my database:

<cfquery name = "comments" datasource = "#DSN#">
SELECT * 
FROM  `forum_comments` 
WHERE topicid = #id#
</cfquery>

Because I don't want to overload my processor while fetching 1000+ comments per topic, I want to seperate all the comments into pages of 10 comments per page. Is this possible with just some little modifications to my page? My best guess to do this is by using the URL.page statement and the LIMIT function in MySQL, but I have no idea how.

Update

All of my current code:

<cfif IsDefined('URL.page')> // Pagination
  <cfset page = URL.page>
<cfelse>
  <cfset page = 1>
</cfif>

<cfset howManyRecsToShow = 10>
<cfset startRec = page*howManyRecsToShow>


<cfquery name = "comments" datasource = "#DSN#"> // Get all comments
SELECT * 
FROM  `forum_comments` 
WHERE topicid = #id#
LIMIT #startRec#, #howManyRecsToShow#
</cfquery>




                <cfset colour ="post_uneven"> // Required for CSS

  <cfloop query="comments"> // Loop over comments


    <div id="post_text">

        <div id="post_text_edit" title="Edit"></div>
        <div id="post_text_delete" title="Delete"></div>

        <div id="post_text_title">
        RE: #gettopic.title#
        </div>

        <div id="post_text_date">
        #DateFormat(dateAdd("s", comments.timestamp, "01/01/1970"))#       #TimeFormat(dateAdd("s", comments.timestamp, "01/01/1970"))#
        </div>

        <div id="post_text_text">
        #comments.text#

        </div>

    </div>

</div>
                    </cfloop>

    </cfoutput>



    <cfif colour is "post_uneven"><cfset colour="post_even"><cfelse><cfset colour="post_uneven"></cfif> // Required for CSS




<div id="topic_info_balk">
<div id="forum_paginas">
   <cfif page gt 1>
    <a href="pageTest.cfm?page=#page-1#">PREVIOUS 10</a>&nbsp;|&nbsp;
  </cfif>
  <a href="?page=<cfoutput>#page+1#</cfoutput>">NEXT 10</a>
</div>
Yannick
  • 235
  • 3
  • 12
  • I'm not convinced that that would 'overload' the database - although it *may* overload your php processor – Strawberry Jan 11 '14 at 16:18
  • You could always cheat and see what others have done. A google search on "coldfusion pagination" will yield many results. – Dan Bracuk Jan 11 '14 at 21:04
  • Already did that, the only things I found were extremely complicated. – Yannick Jan 11 '14 at 21:18
  • 1
    Besides the answer posted, make sure to a) not use `SELECT *`; b) hard-code dynamic values into your SQL statement: use `` to bind them dynamically. – Adam Cameron Jan 11 '14 at 21:34
  • Thanks a lot! In most cases I code everything with simple SQL statements and afterwards I clean it up by using ``, but I haven't found anything that is 'cleaner' then the `SELECT *` function. Would it be better to use `SELECT id, username, email, etcetera`? – Yannick Jan 11 '14 at 21:39
  • 1
    It is always better to select just the fields you need than selecting all available fields. – Dan Bracuk Jan 11 '14 at 21:53
  • Please properly indent your code, then you will see you have extra closing `` tags. – gfrobenius Jan 11 '14 at 22:18
  • ... in your clean up, do not forget to sanitize the LIMIT variables too. I do not recall whether you can use `cfqueryparam` with LIMIT. If not, you could force the input to be numeric with `val(..)`. – Leigh Jan 11 '14 at 23:50
  • @Leigh: no, only *values* can be parameterised. Not parts of the SQL statement. Reading: http://cfmlblog.adamcameron.me/2012/07/what-one-can-and-cannot-do-with.html – Adam Cameron Jan 12 '14 at 15:35
  • Cleaned up the code, thanks for the help! Only problem is that the code gfrobenius posted still isn't working for me. – Yannick Jan 12 '14 at 16:01
  • @AdamCameron - Yep, I as aware of that. I figured most likely he would have to use `val()`. However, I *thought* I recalled something about mySQL behaving a little differently with LIMIT. Now I would not swear to that, but ... I remember being surprised that [cfqueryparam did work with ordinals in mySQL](http://stackoverflow.com/a/893882/104223) at some point. As far as I remember anyway. So just throwing the possibility out there. Though I should have clarified it is more of curiosity / long shot. – Leigh Jan 12 '14 at 22:40
  • @Yannick - You need to clarify "isn't working". What are the actual results of the current code, and how are they different from what you expected? – Leigh Jan 12 '14 at 23:24
  • The whole code doesn't work: it keeps showing the wrong comments when I'm on page 1. Normally it would need to show comment 1 to 10, but instead it shows me 11 to 20. And when I go to page 2, it still shows me the same comments as on page 1. – Yannick Jan 13 '14 at 06:42

1 Answers1

3

You said you want a SIMPLE example so here it is. By SIMPLE I mean this will just show NEXT and PREVIOUS links. If you want slightly more complicated pagination that shows the number of pages then you have to get the total record count before hand. (I quickly free-hand typed this, not on my CF server right now, so not sure if this is 100% accurate)...

(pageTest.cfm)

<cfif IsDefined("url.page")>
  <cfset page = url.page>
<cfelse>
  <cfset page = 1>
</cfif>

<cfset howManyRecsToShow = 10>
<cfset startRec = page*howManyRecsToShow>

<cfquery name="q1">
  select id, username, email
  from users
  order by id limit #startRec# , #howManyRecsToShow#
</cfquery>

<cfoutput>
  <table border="1">
    <cfloop query="q1">
        <tr>
            <td>#q1.id#</td>
            <td>#q1.username#</td>
            <td>#q1.email#</td>
        </tr>
    </cfloop>
  </table>
  <cfif page gt 1>
    <a href="pageTest.cfm?page=#page-1#">PREVIOUS 10</a>&nbsp;|&nbsp;
  </cfif>
  <a href="pageTest.cfm?page=#page+1#">NEXT 10</a>
</cfoutput>
gfrobenius
  • 3,987
  • 8
  • 34
  • 66
  • Really appreciate the example, thanks a lot. Just one question: what is the function of the following cfset? `` - I don't understand the function of the asterisk. – Yannick Jan 11 '14 at 21:38
  • That's multiplication. Example: 2x10=20 – gfrobenius Jan 11 '14 at 21:39
  • Thanks. I think that your example would do the job pretty fine, except that `howManyRecsToShow` remains 10 in every case. So when executing the query on page 2 it would still be `LIMIT 20, 10` and on page 3 `LIMIT 30, 10` instead of `LIMIT 20, 30` and `LIMIT 30, 40` and so on. – Yannick Jan 11 '14 at 21:45
  • That is correct. Read the documentation on the `LIMIT`. Put my code in place and you will see it is correct. You are not understanding `LIMIT` correctly. – gfrobenius Jan 11 '14 at 21:49
  • Read my variable names in the example, I named them so you would understand their purpose: `#startRec#` and `#howManyRecsToShow#`. It's not `FROM` and `TO` like you think. – gfrobenius Jan 11 '14 at 21:57
  • I found an explanation on the internet, and I'm starting to understand it. Sadly, it is not working the way I would like it to be, because on page 1 it shows the same comments as on page 2. But I'll take a closer look at the code. Thanks! – Yannick Jan 11 '14 at 22:02
  • It's working for me so take a closer look or post ALL your code so we can help you more. – gfrobenius Jan 11 '14 at 22:11
  • I've added my current code above. Once again, thank you so much for your help. – Yannick Jan 11 '14 at 22:13