Bruno was working on a PHP-based hotel reservation system and, thanks to the odd bug here and there, seldom had the time to look into the "feature requests" queue. But the good news was that the system was getting more and more stable with each release, and the really good news was that Bruno would be getting some help from a newly hired developer named Greg. Bruno even picked out the perfect first task for the new guy.

The system worked as you'd expect any online hotel reservation system to work – punch in the name of a city (optionally including the number of nights for your stay, smoking/nonsmoking preference, etc.), get a list of hotels back matching the criteria. Clicking the "Find Hotels" button would fire off a few operations; first retrieving a list of hotels from the database, then some light massaging of the list in PHP code, then writing out the results to the page. It was all well and good until you did a search for hotels in New York City, where you'd get a near-endless page with hundreds of hotels. The obvious, simple solution? Split up the results into multiple pages.

Bruno was a little hesitant to give such a simple task to a developer with Greg's qualifications. In pseudocode, it'd require little more than the following:

declare items[], totalItemCount, itemsPerPage
declare numberOfPages, startIndex, endIndex

items[] = loadAllItemsFromDatabase()
items[] = filter ( items[] )

totalItemCount = count( items[] )
numberOfPages = math.ceiling(totalItemCount / itemsPerPage)
startIndex = currentPageIndex * itemsPerPage
endIndex = math.min(startIndex + 10, totalItemCount)

for (i = (currentPageIndex * itemsPerPage) to itemsPerPage)
    writeout ( items[i] )
for (i = 0 to numberOfPages)
    writeout ( buildPageLink(i) )

And if that wasn't simple enough, Bruno found PEAR::Pager, a well-documented pagination plugin for PHP. It would take in a list of items, number of items per page, etc., and build a nice formatted list of pages and items. Bruno pointed Greg to the documentation and asked if he needed any help. "Nope, this looks pretty straightfoward," Greg said with a confident smile, "I'll just need a few days."

"Just remember to run the front-end filters before sending the data to PEAR::Pager," Bruno added, sending him on his way and getting back to reviewing the queue.

Days turned into weeks, with Bruno regularly pinging Greg for updates. Every time, Greg was "alllllllmost done!" and "just putting the final touches on!" Finally, after three weeks of Greg working on the pagination full-time, he was ready to turn it over for testing. Strange, Bruno thought, it seemed like this would be so simple...

New York City‽

Bruno took the keyboard and did a search for hotels in New York City. The resulting page was beautiful – ten results on page one, there was a nice "next page" and page skip option for pages one through ten, and an option for the next batch of pages. Sure Greg had taken a while, but from Bruno's view, it was looking exactly like what he'd envisioned with minimal specs or oversight. "This looks great, Greg!" he said.

Clicking the "next page" link, however, Bruno spotted a bug. The page displayed results 11-20 of over 500, and yet there were only eight hotels listed on the page. "Er, what's happening here," Bruno asked.

"Uhmm..."

Bruno clicked on the next page, and the next page, and he jumped ahead several pages, each time finding different issues. Page three had ten results, page four had six, page five had nine. The final page said it had six, but actually had zero. And on top of that, they weren't sorted correctly.

"Greg, how did you load the list?"

"Well, I take the list from the database and pass it right to PEAR::Pager."

Bruno sank in his chair a little. "We have to do some extra processing and sorting on the front end before this gets sent to the pagination system," he explained. The logic used to calculate distances, for instance, was handled by the front end, as well as real-time checks for vacancies would affect the sorting and remove some results from whatever was returned from the database. Since the database data was passed directly to the pager, and then the collection was modified by the usual front-end processing, there was no consistency on the resulting page. Passing it to the PEAR::Pager after culling the unnecessary results would fix it, easy peasy.

"Oh, ahh, OK..." Greg stammered, red-faced. "Yeah, I noticed that the results were out of order, and that there were a few rows that I had to remove. So, to make it work, I analyzed the page I was going to show, sorted it, and then removed the items that were not to be shown." So he was removing items after they were already set up for certain pages – missing items mystery solved. "I'll get this working, just give me one more day."

This time his estimate was more accurate. By the end of the next day, he was ready for a second demo.

Bruno was feeling cautiously optimistic when he did his second search. Items were sorted correctly, and the first page had ten results, the next, and the next. Bruno's smile grew as he clicked along, and he thanked Greg for the work he did. "Nice job, so this second round wasn't too big of a change?"

"Actually, you'd be surprised." Uh oh. "After I finished this one, I felt like the most intelligent man in the world!"

On page four of the results, Bruno found only eight hotels. One of which had appeared on the previous page.

"Ah, crap," Greg said, frowning.

"Let's take a look at the code, we'll see if we can work this out," Bruno suggested.

The Clever Approach

What Bruno discovered didn't necessarily suggest that Greg was "the most intelligent man in the world," but he was in the running for "the most clever coder in the world." The code was nearly incomprehensible, but Bruno did his best to understand what Greg was trying to accomplish.

In the end, Bruno took it upon himself to rewrite it. In ten minutes, he'd rolled the code file back, and changed the processing to work exactly as he'd asked Greg to do it:

Bruno then spent the remainder of the hour tweaking the look and feel. Within a few weeks of this incident (and after a few similar ones), Greg was disappointed to learn that his services were no longer necessary.