<?xml version="1.0"?>
<rss version="2.0"><channel><title>Craig Campbell - Blog</title><link/><description>Code Ramblings</description><language>en-us</language><pubDate>Sat, 24 Jul 2010 18:22:17 +0000</pubDate><lastBuildDate>Sat, 24 Jul 2010 18:22:17 +0000</lastBuildDate><item><title>Anonymous PHP Functions</title><link>http://www.craigiam.com/blog/anonymous-php-functions/26</link><description>Most PHP developers are probably well aware of this already, but the release of PHP 5.3 brought a few cool features to the language including namespaces, late static binding, and anonymous functions (closures).&lt;br /&gt;
&lt;br /&gt;
In the interest of keeping this brief I just wanted to provide a few simple examples.&lt;br /&gt;
&lt;br /&gt;
Let's imagine you have an array of data:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'id'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'name'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'Tom'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'birthdate'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'1980-05-05'&lt;/span&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'id'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;2&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'name'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'Julia'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'birthdate'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'1985-07-07'&lt;/span&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'id'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;3&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'name'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'Michael'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'birthdate'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'1974-11-17'&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;/div&gt;Now let's say you wanted to grab all the user ids from this array. Normally you would do something like this:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_variable&quot;&gt;$ids&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;();&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;as&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$ids&lt;/span&gt;[]&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'id'&lt;/span&gt;];&lt;br /&gt;}&lt;/div&gt;With anonymous functions you could achieve the same thing by doing:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_variable&quot;&gt;$ids&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array_map&lt;/span&gt;(&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'id'&lt;/span&gt;];&lt;br /&gt;},&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;);&lt;/div&gt;&lt;br /&gt;
Now let's say you wanted to filter out all the users born after 1980.  The traditional way would look something like this:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_variable&quot;&gt;$filtered_users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;();&lt;br /&gt;&lt;span class=&quot;_variable&quot;&gt;$start_date&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;strtotime&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'1979-12-31'&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;as&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_function&quot;&gt;strtotime&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'birthdate'&lt;/span&gt;])&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$start_date&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$filtered_users&lt;/span&gt;[]&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;With anonymous functions:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_variable&quot;&gt;$start_date&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;strtotime&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'1979-12-31'&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;_variable&quot;&gt;$filtered_users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array_filter&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;global&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$start_date&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;strtotime&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'birthdate'&lt;/span&gt;])&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$start_date&lt;/span&gt;;&lt;br /&gt;});&lt;/div&gt;&lt;br /&gt;
I'm not suggesting that you necessarily &lt;em&gt;SHOULD&lt;/em&gt; do this.  The foreach loops are arguably more readable, and in simple benchmarks, they outperform using array functions 90% of the time.  However, it is something else to add to your bag of tricks and can be useful in places where you need a one off callback function.</description><pubDate>Sat, 24 Jul 2010 18:22:17 +0000</pubDate><guid>26</guid><author>Craig Campbell</author></item><item><title>My First GitHub Repository : show-missing-revs</title><link>http://www.craigiam.com/blog/my-first-github-repository-show-missing-revs/25</link><description>I signed up for GitHub a little while ago, but hadn't used the site for anything until just now.&lt;br /&gt;
&lt;br /&gt;
I want to be more open about sharing my code with the world, and I was inspired by the irony of posting a Subversion utility script on GitHub.  &lt;br /&gt;
&lt;br /&gt;
As far as what the script does, it is for finding what revisions in one branch are missing in another. &lt;br /&gt;
I will give a brief overview:&lt;br /&gt;
&lt;br /&gt;
Let's say you are developing a product in trunk and it is time for the 1.2 release.  You create a 1.2 branch from trunk, push it out to the world, and begin developing version 1.3 in trunk.  After 1.2 is released you start getting tons of bug reports.  You work feverishly to fix the bugs in the 1.2 branch but sometimes forget to merge your bugfixes back into trunk.  A month later, you are about ready to release version 1.3 from trunk, but some of the bugs you have already fixed in the 1.2 branch were never merged back into trunk.  If they don't get merged you risk reintroducing bugs you have already fixed!  &lt;br /&gt;
&lt;br /&gt;
How on earth are you going to find out what revisions you forgot to merge?&lt;br /&gt;
&lt;br /&gt;
Subversion has a way of doing this, but all it gives you is the revision numbers.  Using my script you get the revision number, the user who made the commit, and the first line of the commit message.  You have the option to target a specific user.&lt;br /&gt;
&lt;br /&gt;
Using the script looks a little like this:&lt;br /&gt;
&lt;div class=&quot;code shell&quot;&gt;&lt;span class=&quot;_function&quot;&gt;cd&lt;/span&gt;&amp;nbsp;/path/to/trunk&lt;span class=&quot;_function&quot;&gt;&lt;br /&gt;sh&lt;/span&gt;&amp;nbsp;/path/to/show_missing_revs.sh&amp;nbsp;-b&amp;nbsp;1.2&amp;nbsp;-u&amp;nbsp;craig&lt;/div&gt;&lt;br /&gt;
That will output something like:&lt;br /&gt;
&lt;div class=&quot;code shell&quot;&gt;displaying&amp;nbsp;revisions&amp;nbsp;in&amp;nbsp;1.2&amp;nbsp;branch&amp;nbsp;by&amp;nbsp;craig&amp;nbsp;that&amp;nbsp;have&amp;nbsp;not&amp;nbsp;yet&amp;nbsp;been&amp;nbsp;merged&amp;nbsp;to&amp;nbsp;trunk&lt;br /&gt;r127&amp;nbsp;|&amp;nbsp;craig&amp;nbsp;|&amp;nbsp;added&amp;nbsp;awesome&amp;nbsp;stuff&lt;br /&gt;r143&amp;nbsp;|&amp;nbsp;craig&amp;nbsp;|&amp;nbsp;fixed&amp;nbsp;broken&amp;nbsp;awesome&amp;nbsp;stuff&lt;br /&gt;r144&amp;nbsp;|&amp;nbsp;craig&amp;nbsp;|&amp;nbsp;removed&amp;nbsp;debug&amp;nbsp;statement&lt;/div&gt;&lt;br /&gt;
Hopefully someone will find this useful.&lt;br /&gt;
&lt;br /&gt;
You can find it on GitHub at &lt;a rel=&quot;external&quot; href=&quot;http://github.com/ccampbell/show-missing-revs&quot;&gt;http://github.com/ccampbell/show-missing-revs&lt;/a&gt;.</description><pubDate>Wed, 30 Jun 2010 22:38:46 +0000</pubDate><guid>25</guid><author>Craig Campbell</author></item><item><title>Open links in a new browser window using jQuery</title><link>http://www.craigiam.com/blog/open-links-in-a-new-browser-window-using-jquery/24</link><description>I use &lt;a rel=&quot;external&quot; href=&quot;http://www.jquery.com&quot;&gt;jQuery&lt;/a&gt; as my javascript framework of choice because I love how simple it is, and how much you can do with just a single line of code.&lt;br /&gt;
&lt;br /&gt;
I decided it would be a good idea to share some jQuery code snippets to do common tasks.  So hopefully there will be plenty of posts where this one came from.&lt;br /&gt;
&lt;br /&gt;
The easiest way to open a link in a new window is to do something like this:&lt;br /&gt;
&lt;div class=&quot;code html&quot;&gt;&amp;lt;a&amp;nbsp;href=&lt;span class=&quot;_string&quot;&gt;&amp;quot;http://www.google.com&amp;quot;&lt;/span&gt;&amp;nbsp;target=&lt;span class=&quot;_string&quot;&gt;&amp;quot;_blank&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=&quot;_default&quot;&gt;search&amp;nbsp;the&amp;nbsp;web&lt;/span&gt;&amp;lt;/a&amp;gt;&lt;/div&gt;&lt;br /&gt;
Unfortunately, the &lt;span class=&quot;code&quot;&gt;target&lt;/span&gt; attribute is not valid in XHTML strict so you have to use javascript if you want your pages to validate.&lt;br /&gt;
&lt;br /&gt;
The first thing you have to do is give your links some sort of identifier:&lt;br /&gt;
&lt;div class=&quot;code html&quot;&gt;&amp;lt;a&amp;nbsp;href=&lt;span class=&quot;_string&quot;&gt;&amp;quot;http://www.google.com&amp;quot;&lt;/span&gt;&amp;nbsp;rel=&lt;span class=&quot;_string&quot;&gt;&amp;quot;external&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=&quot;_default&quot;&gt;search&amp;nbsp;the&amp;nbsp;web&lt;/span&gt;&amp;lt;/a&amp;gt;&lt;/div&gt;You could use the domain to figure out if the link lives on your site or not, but I prefer to be explicit about which links should open in a new window.&lt;br /&gt;
&lt;br /&gt;
Most tutorials now would recommend that you loop through every link on your page and rewrite them to have the target attribute, but that can be expensive and is not needed.  &lt;br /&gt;
&lt;br /&gt;
All you have to do is add the following javascript code:&lt;br /&gt;
&lt;div class=&quot;code javascript&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_class&quot;&gt;document&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;ready(&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;&amp;quot;a[rel='external']&amp;quot;&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;live(&lt;span class=&quot;_string&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_keyword&quot;&gt;this&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;attr(&lt;span class=&quot;_string&quot;&gt;&amp;quot;target&amp;quot;&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;_blank&amp;quot;&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;});&lt;/div&gt;&lt;br /&gt;
The code is pretty self explanatory, but I will give a brief overview.&lt;br /&gt;
&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;$(document).ready()&lt;/dt&gt;&lt;dd&gt;This is jQuery's way of saying that the page is ready to go.  You can read more about it &lt;a rel=&quot;external&quot; href=&quot;http://docs.jquery.com/Tutorials:Introducing_$(document).ready()&quot;&gt;here&lt;/a&gt;.&lt;/dd&gt;&lt;dt&gt;$(&quot;a[rel='external']&quot;)&lt;/dt&gt;&lt;dd&gt;This is the selector for the links.  This means we are targeting links that have the rel attribute set to &quot;external&quot;.&lt;/dd&gt;&lt;dt&gt;.live&lt;/dt&gt;&lt;dd&gt;.live is similar to .bind but the difference is that .live uses event delegation to bind a single event to the document. This means that all current and future links will exhibit the same behavior. See &lt;a rel=&quot;external&quot; href=&quot;http://api.jquery.com/live/&quot;&gt;this page&lt;/a&gt; for more information.&lt;/dd&gt;&lt;dt&gt;$(this)&lt;/dt&gt;&lt;dd&gt;This turns the link that was clicked into a jQuery object&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;
One additional note about this tutorial is that HTML5 &lt;em&gt;does&lt;/em&gt; support the target attribute so when that is widely used you can forget that this post ever happened.&lt;br /&gt;
</description><pubDate>Mon, 31 May 2010 13:08:39 +0000</pubDate><guid>24</guid><author>Craig Campbell</author></item><item><title>Removing Apple Double &quot;._&quot; files in Mac OS X</title><link>http://www.craigiam.com/blog/removing-apple-double-files-in-mac-os-x/23</link><description>When I work locally on projects I like to use symlinks for all of my shared libraries.  It makes it way easier than having to manage a million different versions of the same files.&lt;br /&gt;
&lt;br /&gt;
Recently I was creating a tarball (.tar) archive to deploy somewhere using the -h option to follow symlinks like so:&lt;br /&gt;
&lt;div class=&quot;code shell&quot;&gt;&lt;span class=&quot;_function&quot;&gt;tar&lt;/span&gt;&amp;nbsp;cvfh&amp;nbsp;code.tar&amp;nbsp;code&lt;/div&gt;&lt;br /&gt;
I noticed that many of the symlinked files that were copied into the archive ended up being transformed into &lt;a rel=&quot;external&quot; href=&quot;http://support.apple.com/kb/TA20578&quot;&gt;apple double&lt;/a&gt; files.  Of course, this is quite annoying, and I wanted to get rid of them.  I did some googling and found the answer buried somewhere on the internets so I thought I'd make it easier to find.&lt;br /&gt;
&lt;br /&gt;
All you have to do is add the following to your  &lt;span class=&quot;code&quot;&gt;~/.bash_profile&lt;/span&gt;:&lt;br /&gt;
&lt;div class=&quot;code shellscript&quot;&gt;&lt;span class=&quot;_comment&quot;&gt;#&amp;nbsp;for&amp;nbsp;Tiger&amp;nbsp;OS&amp;nbsp;10.4&amp;nbsp;or&amp;nbsp;earlier&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;export&lt;/span&gt;&lt;/span&gt;&amp;nbsp;COPY_EXTENDED_ATTRIBUTES_DISABLE&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;true&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;_comment&quot;&gt;#&amp;nbsp;for&amp;nbsp;Leopard&amp;nbsp;OS&amp;nbsp;10.5&amp;nbsp;and&amp;nbsp;later&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;export&lt;/span&gt;&lt;/span&gt;&amp;nbsp;COPYFILE_DISABLE&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;true&lt;/div&gt;&lt;br /&gt;
That's all.</description><pubDate>Mon, 24 May 2010 01:43:56 +0000</pubDate><guid>23</guid><author>Craig Campbell</author></item><item><title>Tonightly has launched!</title><link>http://www.craigiam.com/blog/tonightly-has-launched/21</link><description>I realize most of the things I write about here are pretty technical so it feels a little bit strange to be breaking the mold, but I wanted to let people know about a very exciting project I have been working on in my spare time for nearly the past year.&lt;br /&gt;
&lt;br /&gt;
&lt;a rel=&quot;external&quot; href=&quot;http://www.tonightly.com&quot;&gt;&lt;img src=&quot;http://static.tonightly.com/img/h2_logo.png&quot; alt=&quot;tonightly logo&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The inspiration came one night when I was out with some friends and we were wondering &quot;What is there to do tonight?&quot;. We realized there was no one stop solution to answer this question, and every existing event site out there is cluttered and confusing. The goal for this project was to build a very simple, clean site that would provide event lists for any event happening on the current day.&lt;br /&gt;
&lt;br /&gt;
The functionality is really quite simple. You can register an account or login with your Facebook account to post events. You can post an event for any time in the future, but it won't show up on the site or be searchable until that day rolls around. In the meantime you can still promote it ahead of time on your own site or blog and link your friends to the listing.&lt;br /&gt;
&lt;br /&gt;
You can browse events by rating (hot or not - rotten tomato style), views, neighborhood, or tags and can share events on Twitter, Facebook or via email through Tonightly.&lt;br /&gt;
&lt;br /&gt;
I could go on and on about it, but I think it would be better to go check it out for yourself at &lt;a rel=&quot;external&quot; href=&quot;http://www.tonightly.com&quot;&gt;http://www.tonightly.com&lt;/a&gt;.</description><pubDate>Wed, 14 Apr 2010 02:34:06 +0000</pubDate><guid>21</guid><author>Craig Campbell</author></item><item><title>Pseudo Namespaces With PHP and Memcached Revisited</title><link>http://www.craigiam.com/blog/pseudo-namespaces-with-php-and-memcached-revisited/20</link><description>A while back I &lt;a href=&quot;/blog/pseudo-namespaces-with-php-and-memcached/17&quot;&gt;wrote about&lt;/a&gt; a way to keep data valid across multiple pages by invalidating cache keys. I have since thought of a better way to handle this.&lt;br /&gt;
&lt;br /&gt;
The basic idea is that anytime you have child objects related to a parent object you can use a property of the parent object to invalidate the children. To make this more clear let's revisit the original problem: You are building a blog with a lot of users where each user posts a bunch of articles. The articles are paginated and cached per page. If the user adds a new article, all the items on the page will shift and we need a way to invalidate all the pages in cache.&lt;br /&gt;
&lt;br /&gt;
The approach mentioned in my previous article involved having a namespace key that would store a random integer which would then be incremented when there is an update. This has a few problems:&lt;br /&gt;
&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;It is never 100% safe to rely on random numbers.&lt;/dt&gt;&lt;dd&gt;If there is a cache failure on one server and the namespace key falls out of cache then there is a chance that the random number generated will lead to a key containing data that was in cache a while ago.  Also on that same note incrementing the version could still contain stale data in cache.&lt;/dd&gt;&lt;dt&gt;It creates unnecessary cache lookups.&lt;/dt&gt;&lt;dd&gt;The namespace lookups have to happen before you can perform the initial lookup.  Cache is fast, but like anything else it should only be used when necessary.&lt;/dd&gt;&lt;dt&gt;It can cause cache contention issues.&lt;/dt&gt;&lt;dd&gt;If many people are all trying to access the same key at the same time then the requests start to bubble up and the last one has to wait for the others to finish.  This is more prevalent in this situation because if there are 10 pages of articles, each page would have its own unique cache key, but all 10 pages would share the same namespace key.&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;
Enough with the problems, let's take a look at the solution:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;class&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;User&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_lastArticleUpdate&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getArticles&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$page&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pageSize&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$cacheKey&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$page&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pageSize&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_lastArticleUpdate;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;((&lt;span class=&quot;_variable&quot;&gt;$articles&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;Cache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;::&lt;/span&gt;&lt;/span&gt;get(&lt;span class=&quot;_variable&quot;&gt;$cacheKey&lt;/span&gt;))&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$articles&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;cache&amp;nbsp;miss,&amp;nbsp;retrieve&amp;nbsp;articles&amp;nbsp;from&amp;nbsp;database&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
This is overly simplified, but you can see how much cleaner and simpler this approach is. The &lt;span class=&quot;code&quot;&gt;lastArticleUpdate&lt;/span&gt; property contains a timestamp. This timestamp would get updated everytime the user adds/removes/updates an article. Since the user object is already required in order to get a page of articles in this example, you already have this property accessible.</description><pubDate>Tue, 09 Mar 2010 02:27:54 +0000</pubDate><guid>20</guid><author>Craig Campbell</author></item><item><title>Memcached Multiget using PHP PECL Memcache class</title><link>http://www.craigiam.com/blog/memcached-multiget-using-php-pecl-memcache-class/19</link><description>At work I have been working with memcache quite a bit and coming up with creative ways to cache stuff. Perhaps I will elaborate on some of these in later posts, but for now I think I will focus on one interesting issue I ran into using multiget.&lt;br /&gt;
&lt;br /&gt;
Using PECL Memcache extension the &lt;span class=&quot;code&quot;&gt;Memcache::get()&lt;/span&gt; method allows you to pass in a single key as a string or an array of keys to retrieve from cache. This can be very useful for retrieving lots of information with one request to memcache, however, there are a couple things to keep in mind. The first is something minor that I found annoying.&lt;br /&gt;
&lt;br /&gt;
Let's say you request &lt;span class=&quot;code&quot;&gt;array('item_1', 'item_2')&lt;/span&gt; from cache. If only item 1 is in cache then the resulting array will be something like this: &lt;span class=&quot;code&quot;&gt;array('item_1' =&gt; 'this is the value for item 1')&lt;/span&gt;. This means you have to actually check if a key exists in the resulting array or not in order to know how to proceed.&lt;br /&gt;
&lt;br /&gt;
The second thing had me banging my head against the wall for a short while since it was not possible to reproduce on a development environment. If you request multiple items from cache in one multiget request and the items requested are distributed over more than one server then they will not be returned in the same order that they were requested in.&lt;br /&gt;
&lt;br /&gt;
While this seems to be the expected behavior, I couldn't find any information or documentation about this in the PHP documentation for &lt;a rel=&quot;external&quot; href=&quot;http://www.php.net/manual/en/function.memcache-get.php&quot;&gt;memcache&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
After a little while I thought of a workaround to this problem. The code is as follows:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&amp;lt;?php&lt;br /&gt;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;multiple&amp;nbsp;keys&amp;nbsp;from&amp;nbsp;cache&amp;nbsp;and&amp;nbsp;returns&amp;nbsp;the&amp;nbsp;values&amp;nbsp;in&amp;nbsp;the&amp;nbsp;same&amp;nbsp;order&lt;br /&gt;&amp;nbsp;*&amp;nbsp;they&amp;nbsp;were&amp;nbsp;requested&amp;nbsp;in&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;array&amp;nbsp;$keys&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;bool&amp;nbsp;$preserveOrder&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;array&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getMulti&lt;/span&gt;(&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$keys&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$preserveOrder&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;true&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;grab&amp;nbsp;whatever&amp;nbsp;items&amp;nbsp;we&amp;nbsp;can&amp;nbsp;from&amp;nbsp;cache&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$items&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;get(&lt;span class=&quot;_variable&quot;&gt;$keys&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;we&amp;nbsp;don't&amp;nbsp;care&amp;nbsp;what&amp;nbsp;order&amp;nbsp;the&amp;nbsp;keys&amp;nbsp;are&amp;nbsp;returned&amp;nbsp;in&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_keyword&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;_variable&quot;&gt;$preserveOrder&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$items&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;set&amp;nbsp;all&amp;nbsp;keys&amp;nbsp;to&amp;nbsp;null&amp;nbsp;so&amp;nbsp;if&amp;nbsp;something&amp;nbsp;is&amp;nbsp;not&amp;nbsp;found&amp;nbsp;in&amp;nbsp;cache&amp;nbsp;it&amp;nbsp;won't&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;be&amp;nbsp;set&amp;nbsp;to&amp;nbsp;a&amp;nbsp;value&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$results&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array_fill_keys&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$keys&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;merge&amp;nbsp;the&amp;nbsp;two&amp;nbsp;arrays&amp;nbsp;so&amp;nbsp;the&amp;nbsp;returned&amp;nbsp;values&amp;nbsp;from&amp;nbsp;cache&amp;nbsp;overwrite&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;the&amp;nbsp;starting&amp;nbsp;values&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array_merge&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$results&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$items&lt;/span&gt;);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
This pretty much solves both of the problems mentioned above. By using &lt;span class=&quot;code&quot;&gt;array_fill_keys&lt;/span&gt; we are able to guarantee that every item will be returned in the resulting array. By using &lt;span class=&quot;code&quot;&gt;array_merge&lt;/span&gt; any of the items actually returned will overwrite the values in the original while preserving the same order&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;Please note this code is part of a Memcache wrapper class.&lt;/em&gt; </description><pubDate>Mon, 28 Dec 2009 00:57:21 +0000</pubDate><guid>19</guid><author>Craig Campbell</author></item><item><title>Post processing search results without running SQL queries in loops</title><link>http://www.craigiam.com/blog/post-processing-search-results-without-running-sql-queries-in-loops/18</link><description>Recently at work we were presented with an interesting problem, one of many problems that came up from using the &lt;a rel=&quot;external&quot; href=&quot;http://www.google.com/gsa&quot;&gt;Google Search Appliance&lt;/a&gt; to index and handle search results on a large site (I will probably touch on some of the others in future blog posts). The problem is this:&lt;br /&gt;
&lt;br /&gt;
We have a site containing many content items that are all indexed by the Google Search Appliance. We have to manually feed XML to the GSA since we have very specific business requirements and allowing Google to crawl our site will not work. This means that when there are updates to items we need to let the GSA know to reindex this item with the correct information. For most things this is fine, but for ratings if we have to queue an item up each time a user rates an item that would significantly slow down the site and prove to not be the best solution. The rating does not have to be 100% up to the minute, but if something is indexed today and then rated 100 times without being reindexed, the rating in the index could be very far off. This means we needed a way to keep the item's ratings accurate in the search results.&lt;br /&gt;
&lt;br /&gt;
The solution I came up with (with the help of my coworker, &lt;a rel=&quot;external&quot; href=&quot;http://www.josephjorgensen.com&quot;&gt;Joseph&lt;/a&gt;) was to cache an array of (itemId =&gt; rating). The first idea was to cache everything at once, but considering the number of items is constantly growing there is a chance that this would exceed Memcached's 1MB limit per item in cache. So we decided to split the cache up into groups so some items would be in the first array, some in the second, etc.&lt;br /&gt;
&lt;br /&gt;
One thing to keep in mind here is that we are already storing a de-normalized rating value so we do not have to calculate averages over huge amounts of data when we need to select an item's rating. That would almost certainly break this approach.&lt;br /&gt;
&lt;br /&gt;
The final code looks something like this:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&amp;lt;?php&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getRating&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$itemId&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$numGroups&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;5&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$mod&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$itemId&lt;/span&gt;&amp;nbsp;%&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$numGroups&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$cacheKey&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$mod&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;((&lt;span class=&quot;_variable&quot;&gt;$ratings&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;Core_Environment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;::&lt;/span&gt;&lt;/span&gt;getCache()&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;get(&lt;span class=&quot;_variable&quot;&gt;$cacheKey&lt;/span&gt;))&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'/*&amp;nbsp;'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'&amp;nbsp;*/'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;SELECT&amp;nbsp;i.id&amp;nbsp;id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i.rating&amp;nbsp;rating&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;item&amp;nbsp;i&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;MOD(i.id,&amp;quot;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$numGroups&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;)&amp;nbsp;=&amp;nbsp;:mod&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_db&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;prepare(&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;bindValue(&lt;span class=&quot;_string&quot;&gt;':mod'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$mod&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;execute();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;fetchAllAssoc();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;format&amp;nbsp;the&amp;nbsp;array&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$ratings&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;as&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$ratings&lt;/span&gt;[&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'id'&lt;/span&gt;]]&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'rating'&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;Core_Environment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;::&lt;/span&gt;&lt;/span&gt;getCache()&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;put(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$cacheKey&lt;/span&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$ratings&lt;/span&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;3600&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$ratings&lt;/span&gt;[&lt;span class=&quot;_variable&quot;&gt;$itemId&lt;/span&gt;];&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
I think this is pretty self explanatory, but I will give a brief overview. Basically I am using the &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Modulo_operation&quot;&gt;Modulo Operation&lt;/a&gt; to handle the cache grouping. With the number of groups set to 5, the remainder will always be a number between 0 and 4. This allows us to easily group the items into those 5 categories. This also means if there are 20,000 items in the system each group would contain 4,000 items (assuming the ids are all sequential). This allows us to call the getRating() method for each item returned in the search results, and chances are pretty good that they will all hit cache.&lt;br /&gt;
&lt;br /&gt;
I know this might not always be necessary considering 1MB &amp;#61; 1,048,576 bytes and even if you figure as high as 15 bytes per item that could hold almost 70,000 item ratings in one array, but smaller arrays are easier/faster to work with, and it is better to be safe than sorry. I would also recommend storing the number of groups and cache expiration times in a configuration file somewhere so you don't need to make code changes to update them.</description><pubDate>Sat, 29 Aug 2009 21:41:59 +0000</pubDate><guid>18</guid><author>Craig Campbell</author></item><item><title>Pseudo Namespaces With PHP and Memcached</title><link>http://www.craigiam.com/blog/pseudo-namespaces-with-php-and-memcached/17</link><description>&lt;strong&gt;UPDATED&lt;/strong&gt; 09 MAR 2010 &lt;a href=&quot;/blog/pseudo-namespaces-with-php-and-memcached-revisited/20&quot;&gt;SEE THIS POST&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I have been so incredibly busy lately that I have not had anytime to write here. Anyway I just wanted to take some time to talk about something cool I have been doing for a project I have been working on outside of work.&lt;br /&gt;
&lt;br /&gt;
By now everyone knows what &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Memcached&quot;&gt;Memcached&lt;/a&gt; is so I won't bore you with an introduction. Basically it is an insanely simple caching system designed to eliminate load on the database.&lt;br /&gt;
&lt;br /&gt;
While in an ideal world you would just throw cache on everything and watch your application scale to infinity and beyond, things aren't always that simple. The problem I'm going to show you today has to do with pagination and cached database queries. I will try to make this pretty straightforward so anyone can follow.&lt;br /&gt;
&lt;br /&gt;
There is a user named Pablo Picasso who is using your site. He makes &lt;a rel=&quot;external&quot; href=&quot;http://www.cap-sac.com&quot;&gt;Cap-Sacs&lt;/a&gt; for a living and has received 15 messages from people on the site who are interested in purchasing one from him. This means that page 1 displays messages 6 to 15 (the 10 most recent messages) and page 2 displays 1 to 5.&lt;br /&gt;
&lt;br /&gt;
Let's now imagine you cache these pages of results. A new user comes to your site and wants to buy a pink Cap-Sac. They send Picasso a message so your application says, &quot;Oooh Picasso just got a new message. That's pretty rad. Since the query to get his messages is Cached let's just drop the cache for page 1.&quot; Now what happens you ask?&lt;br /&gt;
&lt;br /&gt;
The new message shows up on the top of page 1 as expected so what's the problem?? Picasso now has 16 messages. Page 1 will display messages 7 to 16 which is fine, but since page 2 was cached from before it is going to show messages 1 to 5 still. This means that as long as the cache lives poor message number 6 (the last message on page 1 before the new message was recieved) gets dropped from the result set completely. Not to mention that page 1 thinks Picasso has 16 messages while page 2 still thinks he has 15.&lt;br /&gt;
&lt;br /&gt;
This can also allow duplicates of the same item to show up if for example the user had 22 messages and page 1 and 2 were cached but page 3 wasn't. In this case a new message would cause page 3 and page 1 to be correct but since page 2 is still hitting cache, the last item on page 2 would be the same as the first item on page 3.&lt;br /&gt;
&lt;br /&gt;
So what can we do about this? I see a few options&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Don't use memcached for paginated result sets&lt;/li&gt;&lt;li&gt;Live with missing and/or duplicate items from time to time in your pagination&lt;/li&gt;&lt;li&gt;Select everything at once and handle the pagination at the PHP level instead of in the database&lt;/li&gt;&lt;li&gt;Use Pseudo cache namespaces to invalidate all cache keys for paginated queries&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;
&lt;br /&gt;
And here is my analysis of the options:&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;Option 1&lt;/dt&gt;&lt;dd&gt;This seems to be the approach that is often taken where I work, and of course it will work, but what happens if the data rarely changes?  In that case it seems rather silly to continue to hit the database over and over for the same data.&lt;/dd&gt;&lt;dt&gt;Option 2&lt;/dt&gt;&lt;dd&gt;Surprisingly I don't think option 2 is a terrible option because it will definitely scale pretty well.  Facebook search results have duplicate items all over most likely for this very reason, but since, in my example, I am thinking about displaying accurate data to the user I would stay away from this.  For search results I think this is a much more viable option.&lt;/dd&gt;&lt;dt&gt;Option 3&lt;/dt&gt;&lt;dd&gt;This option is another interesting one.  It would arguably scale better than any of the other options I have proposed although the problem here is what if Lady Gaga is using your site and she has 15,000 messages from fans.  We don't want to have to select 15,000 items from the database if this were to miss cache.&lt;/dd&gt;&lt;dt&gt;Option 4&lt;/dt&gt;&lt;dd&gt;Well considering the title of this post I think you all knew this is the road I was going to go down.  You get the performance benefits of caching, and you get 100 percent data accuracy.&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;
&lt;br /&gt;
The approach here is really quite simple and similar to the example found on the memcached &lt;a rel=&quot;external&quot; href=&quot;http://code.google.com/p/memcached/wiki/FAQ#Simulating_Namespaces_with_key_prefixes&quot;&gt;FAQ&lt;/a&gt; page.&lt;br /&gt;
&lt;br /&gt;
What I have chosen to do is use the DAO name as my main namespace identifier along with the unique userId. Please understand this is a very crude implementation just to illustrate my idea. It is more or less procedural code so I would not recommend doing it like this. I have been using a Cache_Namespace class to handle common logic such as generating the key and grabbing/setting the generation version/incrementing the version. Anyway here goes:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&amp;lt;?php&lt;br /&gt;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;this&amp;nbsp;would&amp;nbsp;get&amp;nbsp;called&amp;nbsp;to&amp;nbsp;retrieve&amp;nbsp;a&amp;nbsp;page&amp;nbsp;of&amp;nbsp;a&amp;nbsp;user's&amp;nbsp;messages&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getMessages&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$userId&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pageNumber&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Memcache&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;this&amp;nbsp;is&amp;nbsp;the&amp;nbsp;cache&amp;nbsp;key&amp;nbsp;to&amp;nbsp;use&amp;nbsp;to&amp;nbsp;find&amp;nbsp;the&amp;nbsp;version&amp;nbsp;to&amp;nbsp;use&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$versionKey&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'Message_Dao_'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$userId&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_version'&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;there&amp;nbsp;is&amp;nbsp;no&amp;nbsp;cache&amp;nbsp;hit&amp;nbsp;for&amp;nbsp;the&amp;nbsp;version&amp;nbsp;set&amp;nbsp;it&amp;nbsp;to&amp;nbsp;a&amp;nbsp;random&amp;nbsp;value&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;and&amp;nbsp;set&amp;nbsp;it&amp;nbsp;to&amp;nbsp;never&amp;nbsp;expire&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;((&lt;span class=&quot;_variable&quot;&gt;$version&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;get(&lt;span class=&quot;_variable&quot;&gt;$versionKey&lt;/span&gt;))&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;we&amp;nbsp;should&amp;nbsp;use&amp;nbsp;a&amp;nbsp;random&amp;nbsp;number&amp;nbsp;here&amp;nbsp;because&amp;nbsp;otherwise&amp;nbsp;there&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;is&amp;nbsp;a&amp;nbsp;chance&amp;nbsp;the&amp;nbsp;version&amp;nbsp;key&amp;nbsp;will&amp;nbsp;expire&amp;nbsp;and&amp;nbsp;resetting&amp;nbsp;it&amp;nbsp;to&amp;nbsp;1&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;means&amp;nbsp;incrementing&amp;nbsp;it&amp;nbsp;might&amp;nbsp;not&amp;nbsp;invalidate&amp;nbsp;all&amp;nbsp;cache&amp;nbsp;keys&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;the&amp;nbsp;query&amp;nbsp;has&amp;nbsp;been&amp;nbsp;cached&amp;nbsp;at&amp;nbsp;version&amp;nbsp;2&amp;nbsp;for&amp;nbsp;example&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$version&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;rand&lt;/span&gt;(&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;9999&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;put(&lt;span class=&quot;_variable&quot;&gt;$versionKey&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$version&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;this&amp;nbsp;will&amp;nbsp;be&amp;nbsp;the&amp;nbsp;key&amp;nbsp;we&amp;nbsp;use&amp;nbsp;to&amp;nbsp;actually&amp;nbsp;retrieve&amp;nbsp;the&amp;nbsp;data&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$queryCacheKey&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$userId&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pageNumber&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$version&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;there&amp;nbsp;is&amp;nbsp;no&amp;nbsp;cache&amp;nbsp;hit&amp;nbsp;for&amp;nbsp;this&amp;nbsp;data&amp;nbsp;then&amp;nbsp;we&amp;nbsp;need&amp;nbsp;to&amp;nbsp;run&amp;nbsp;the&amp;nbsp;query&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;((&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;get(&lt;span class=&quot;_variable&quot;&gt;$queryCacheKey&lt;/span&gt;))&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;run&amp;nbsp;query&amp;nbsp;here&amp;nbsp;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;blah&amp;nbsp;blah&amp;nbsp;blah&amp;nbsp;blah&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;grab&amp;nbsp;the&amp;nbsp;result&amp;nbsp;set&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;fetchAssoc();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;store&amp;nbsp;the&amp;nbsp;results&amp;nbsp;in&amp;nbsp;cache&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;put(&lt;span class=&quot;_variable&quot;&gt;$queryCacheKey&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;this&amp;nbsp;would&amp;nbsp;get&amp;nbsp;called&amp;nbsp;when&amp;nbsp;a&amp;nbsp;user&amp;nbsp;sends&amp;nbsp;another&amp;nbsp;user&amp;nbsp;a&amp;nbsp;message&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;sendMessage&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$message&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$toId&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$fromId&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;run&amp;nbsp;insert&amp;nbsp;INSERT&amp;nbsp;INTO&amp;nbsp;message&amp;nbsp;blah&amp;nbsp;blah&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;after&amp;nbsp;adding&amp;nbsp;the&amp;nbsp;message&amp;nbsp;to&amp;nbsp;the&amp;nbsp;database&amp;nbsp;we&amp;nbsp;need&amp;nbsp;to&amp;nbsp;invalidate&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;all&amp;nbsp;cache&amp;nbsp;keys&amp;nbsp;for&amp;nbsp;the&amp;nbsp;person&amp;nbsp;you&amp;nbsp;are&amp;nbsp;sending&amp;nbsp;it&amp;nbsp;to&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$versionKey&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'Message_Dao_'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$toId&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_version'&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Memcache&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;we&amp;nbsp;call&amp;nbsp;add&amp;nbsp;here&amp;nbsp;because&amp;nbsp;increment&amp;nbsp;won't&amp;nbsp;increment&amp;nbsp;a&amp;nbsp;value&amp;nbsp;that&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;does&amp;nbsp;not&amp;nbsp;exist.&amp;nbsp;&amp;nbsp;add()&amp;nbsp;will&amp;nbsp;only&amp;nbsp;set&amp;nbsp;a&amp;nbsp;value&amp;nbsp;if&amp;nbsp;it&amp;nbsp;doesn't&amp;nbsp;exist&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;otherwise&amp;nbsp;it&amp;nbsp;will&amp;nbsp;return&amp;nbsp;false&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;add(&lt;span class=&quot;_variable&quot;&gt;$versionKey&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;rand&lt;/span&gt;(&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;9999&lt;/span&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$memcache&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;increment(&lt;span class=&quot;_variable&quot;&gt;$versionKey&lt;/span&gt;);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
I tried to comment that code pretty well. As you can see the version is used as part of the query cache key so incrementing its value by 1 will make all calls to that method not hit cache. If you have more than one method you want to invalidate you can give them the same namespace key as seen in line 11.&lt;br /&gt;
&lt;br /&gt;
Okay that is all for now.</description><pubDate>Wed, 27 May 2009 00:02:53 +0000</pubDate><guid>17</guid><author>Craig Campbell</author></item><item><title>Simple Pagination With PHP and MySQL</title><link>http://www.craigiam.com/blog/simple-pagination-with-php-and-mysql/16</link><description>Just when you thought I had run out of material to write about I am back! I have a few topics still lined up, but I have been so busy that I haven't had time to write anything.&lt;br /&gt;
&lt;br /&gt;
The project I have been working on at work has lots of pagination in it, and the other day I was really frustrated with how difficult it was to do simple pagination and how many lines of code it took in the controller. Here I am going to present to you a pagination class I wrote and a usage example.&lt;br /&gt;
&lt;br /&gt;
I am aware that there is a Zend_Pagination class in Zend Framework, but I'm not crazy about it. It offers some nice view helpers to draw pagination on a page, however, it is over 900 lines long, contains a lot of code you probably will never need, and is missing simple functions that you may need such as determining the page offset or the first and last item on the current page.&lt;br /&gt;
&lt;br /&gt;
Here is the class I have written in its entirety (all of 237 lines including comments):&lt;br /&gt;
&lt;div class=&quot;code php&quot; style=&quot;height:400px;&quot;&gt;&amp;lt;?php&lt;br /&gt;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;Pager&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@package&amp;nbsp;Pager&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@author&amp;nbsp;Craig&amp;nbsp;Campbell&amp;nbsp;&amp;lt;iamcraigcampbell@gmail.com&amp;gt;&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;class&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;Pager&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&amp;nbsp;in&amp;nbsp;the&amp;nbsp;data&amp;nbsp;set&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_totalItems&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;pages&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_totalPages&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&amp;nbsp;per&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_pageSize&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;current&amp;nbsp;page&amp;nbsp;number&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_currentPage&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;first&amp;nbsp;item&amp;nbsp;on&amp;nbsp;current&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_firstOnPage&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;last&amp;nbsp;item&amp;nbsp;on&amp;nbsp;current&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_lastOnPage&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;constructor&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;int&amp;nbsp;$page&amp;nbsp;page&amp;nbsp;number&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;int&amp;nbsp;$pageSize&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&amp;nbsp;per&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;__construct&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$page&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pageSize&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;10&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$page&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Exception&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'page&amp;nbsp;cannot&amp;nbsp;be&amp;nbsp;less&amp;nbsp;than&amp;nbsp;1!'&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$page&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$pageSize&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Exception&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'page&amp;nbsp;size&amp;nbsp;cannot&amp;nbsp;be&amp;nbsp;less&amp;nbsp;than&amp;nbsp;1!'&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_pageSize&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pageSize&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;sets&amp;nbsp;the&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&amp;nbsp;in&amp;nbsp;this&amp;nbsp;data&amp;nbsp;set&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;usually&amp;nbsp;comes&amp;nbsp;from&amp;nbsp;some&amp;nbsp;kind&amp;nbsp;of&amp;nbsp;count&amp;nbsp;query&amp;nbsp;in&amp;nbsp;the&amp;nbsp;database&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;int&amp;nbsp;$number&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;setTotalItems&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$number&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalItems&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$number&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;the&amp;nbsp;first&amp;nbsp;item&amp;nbsp;on&amp;nbsp;this&amp;nbsp;page&amp;nbsp;will&amp;nbsp;be&amp;nbsp;one&amp;nbsp;above&amp;nbsp;the&amp;nbsp;offset&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_firstOnPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getOffset()&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;pages&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalPages&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;ceil(&lt;span class=&quot;_variable&quot;&gt;$number&lt;/span&gt;&amp;nbsp;/&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_pageSize);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;the&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&amp;nbsp;is&amp;nbsp;greater&amp;nbsp;than&amp;nbsp;the&amp;nbsp;first&amp;nbsp;item&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;and&amp;nbsp;there&amp;nbsp;are&amp;nbsp;more&amp;nbsp;pages&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$number&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_firstOnPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;amp;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalPages&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage)&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_lastOnPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getOffset()&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_pageSize;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_lastOnPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$number&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;determine&amp;nbsp;the&amp;nbsp;offset&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getOffset&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;)&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;*&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_pageSize;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;determines&amp;nbsp;if&amp;nbsp;there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;previous&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;hasPrevious&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;)&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;determines&amp;nbsp;if&amp;nbsp;there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;next&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;hasNext&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;)&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;lt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalPages;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;previous&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getPrevious&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;hasPrevious())&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;next&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getNext&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;hasNext())&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&amp;nbsp;on&amp;nbsp;the&amp;nbsp;current&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getCurrentPageSize&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_lastOnPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_firstOnPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;current&amp;nbsp;page&amp;nbsp;size&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getPageSize&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_pageSize;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;pages&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getTotalPages&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalPages;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;first&amp;nbsp;item&amp;nbsp;on&amp;nbsp;the&amp;nbsp;current&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getFirstOnPage&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_firstOnPage;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;last&amp;nbsp;item&amp;nbsp;on&amp;nbsp;the&amp;nbsp;current&amp;nbsp;page&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getLastOnPage&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_lastOnPage;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;current&amp;nbsp;page&amp;nbsp;number&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getCurrentPage&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;the&amp;nbsp;total&amp;nbsp;number&amp;nbsp;of&amp;nbsp;items&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getTotalItems&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalItems;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;determines&amp;nbsp;if&amp;nbsp;the&amp;nbsp;current&amp;nbsp;page&amp;nbsp;has&amp;nbsp;content&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;hasContent&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_currentPage&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;lt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_totalPages;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Keep in mind this is a rough draft, but it seems to work pretty well. All you need to tell the class is 3 things:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The current page number in the constructor&lt;/li&gt;&lt;li&gt;The number of items you would like to see per page in the constructor&lt;/li&gt;&lt;li&gt;The total number of items that you will be paginating in the setTotalItems() method&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;
Now here is an example of this class in action (controller):&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Pager&lt;/span&gt;($&lt;span class=&quot;_int&quot;&gt;_GET&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'page'&lt;/span&gt;],&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;15&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;_variable&quot;&gt;$dao&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;User_Dao&lt;/span&gt;();&lt;br /&gt;&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$dao&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getAll(&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;);&lt;/div&gt;&lt;br /&gt;
Here is the method in the User_Dao to get the users from the database:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;gets&amp;nbsp;all&amp;nbsp;users&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;Pager&amp;nbsp;$pager&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;Collection&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;getAll&lt;/span&gt;(&lt;span class=&quot;_function&quot;&gt;Pager&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'/*&amp;nbsp;'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'&amp;nbsp;*/'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;SELECT&amp;nbsp;SQL_CALC_FOUND_ROWS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;u.id&amp;nbsp;id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;u.email&amp;nbsp;email&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;user&amp;nbsp;u&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ORDER&amp;nbsp;BY&amp;nbsp;u.id&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LIMIT&amp;nbsp;$pager-&amp;gt;getPageSize()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OFFSET&amp;nbsp;$pager-&amp;gt;getOffset()&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_db&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;prepare(&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;execute();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;fetchAllAssoc();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'/*&amp;nbsp;'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'&amp;nbsp;*/'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;SELECT&amp;nbsp;FOUND_ROWS()&amp;nbsp;as&amp;nbsp;total_records&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$totalStatement&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_db&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;prepare(&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$totalStatement&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;execute();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$totalStatement&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;fetchAssoc();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;setTotalItems(&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'total_records'&lt;/span&gt;]);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_buildCollection(&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
There are a few things to note here. &lt;a rel=&quot;external&quot; href=&quot;http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows&quot;&gt;SQL_CALC_FOUND_ROWS&lt;/a&gt; is a totally awesome mysql function that calculates the number of rows that would be returned if you did not include a LIMIT on the query. This is what is used to tell the pager how many total items there are. Also the DAO here is returning a collection. To see how that works check out &lt;a href=&quot;/blog/cool-object-building-with-php/13&quot;&gt;this post&lt;/a&gt; I wrote a little while ago.&lt;br /&gt;
&lt;br /&gt;
Since PHP passes objects by reference by default we can now use the same Pager object that we instantiated in our controller in our view. That would look something like this:&lt;br /&gt;
&lt;div class=&quot;code html&quot;&gt;&amp;lt;h2&amp;gt;&lt;span class=&quot;_default&quot;&gt;Page&amp;nbsp;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getCurrentPage();&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;nbsp;of&amp;nbsp;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getTotalPages();&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;/h2&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&lt;/span&gt;&amp;lt;h3&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Displaying&amp;nbsp;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getFirstOnPage();&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;amp;mdash;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getLastOnPage();&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;nbsp;of&amp;nbsp;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getTotalItems();&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;nbsp;Users&lt;br /&gt;&lt;/span&gt;&amp;lt;/h3&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$users&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;as&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;):&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;dl&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;dt&amp;gt;&lt;span class=&quot;_default&quot;&gt;id&lt;/span&gt;&amp;lt;/dt&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;dd&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;id;&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;/dd&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;dt&amp;gt;&lt;span class=&quot;_default&quot;&gt;email&lt;/span&gt;&amp;lt;/dt&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;dd&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;email;&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;/dd&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/dl&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;endforeach&lt;/span&gt;;&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;hasPrevious()):&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;p&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;/span&gt;&amp;lt;a&amp;nbsp;href=&lt;span class=&quot;_string&quot;&gt;&amp;quot;/view-users?page=&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getPrevious();&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=&quot;_default&quot;&gt;previous&lt;/span&gt;&amp;lt;/a&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;/span&gt;&amp;lt;/p&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;endif&lt;/span&gt;;&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;hasNext()):&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;p&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;/span&gt;&amp;lt;a&amp;nbsp;href=&lt;span class=&quot;_string&quot;&gt;&amp;quot;/view-users?page=&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;echo&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$pager&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;getNext();&amp;nbsp;?&amp;gt;&lt;/span&gt;&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=&quot;_default&quot;&gt;next&lt;/span&gt;&amp;lt;/a&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;/span&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;span class=&quot;_default&quot;&gt;&amp;lt;?php&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;endif&lt;/span&gt;;&amp;nbsp;?&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
I'm probably forgetting something here, but I think it is a good start and in my opinion it certainly eliminates any headaches caused from having to deal with pagination.</description><pubDate>Sat, 04 Apr 2009 02:41:30 +0000</pubDate><guid>16</guid><author>Craig Campbell</author></item><item><title>How to make an overlay using only one div</title><link>http://www.craigiam.com/blog/how-to-make-an-overlay-using-only-one-div/15</link><description>One thing I have realized in my journey across the internets is that there is no simple, clear way to make an overlay using only one div (at least that I could find). If you have no clue what I am talking about click on the &quot;add comment&quot; link, and you will see. The page dims, the curtain goes up and the audience applauds.&lt;br /&gt;
&lt;br /&gt;
Just a small disclaimer: The CSS that I am about to show you will work just fine in all browsers except for Internet Explorer 6 (what a shock!). I will show you the necessary Javascript (using jQuery) needed to fix this.&lt;br /&gt;
&lt;br /&gt;
The first step is to simply add one div inside the body tag like so:&lt;br /&gt;
&lt;div class=&quot;code html&quot;&gt;&amp;lt;body&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;div&amp;nbsp;id=&lt;span class=&quot;_string&quot;&gt;&amp;quot;overlay&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;/span&gt;&lt;span class=&quot;_comment&quot;&gt;&amp;lt;!--&amp;nbsp;this&amp;nbsp;is&amp;nbsp;the&amp;nbsp;overlay&amp;nbsp;:)&amp;nbsp;--&amp;gt;&lt;/span&gt;&lt;span class=&quot;_default&quot;&gt;&lt;/span&gt;&amp;lt;/div&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&lt;/span&gt;&amp;lt;/body&amp;gt;&lt;/div&gt;&lt;br /&gt;
The next step is to add the following to your stylesheet:&lt;br /&gt;
&lt;div class=&quot;code css&quot;&gt;&lt;span class=&quot;_method&quot;&gt;#overlay&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;none&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;fixed&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;top&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;left&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;%&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;%&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;z-index&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1000&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-color&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;#&lt;span class=&quot;_int&quot;&gt;333&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_default&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-moz-opacity&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;0.5&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;opacity&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;.50&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;filter:&amp;nbsp;progid&lt;/span&gt;:DXImageTransform&lt;span class=&quot;_int&quot;&gt;.&lt;/span&gt;Microsoft&lt;span class=&quot;_int&quot;&gt;.&lt;/span&gt;Alpha(opacity=&lt;span class=&quot;_int&quot;&gt;50&lt;/span&gt;);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
To go through this step by step:&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;display: none&lt;/dt&gt;&lt;dd&gt;This simply means don't show this div.  The reason is obvious since we don't want our entire page to load with a colour on top of it.  One thing to note is that we will have to use javascript to set the display here to block or something other than none when we want this to show up on the page.&lt;/dd&gt;&lt;dt&gt;position: fixed&lt;/dt&gt;&lt;dd&gt;This means that the top left point of the div is fixed at point (0,0) or whatever point you specify.  This means intelligent browsers can scale the width and height to cover the whole window&lt;/dd&gt;&lt;dt&gt;z-index: 1000&lt;/dt&gt;&lt;dd&gt;You can think of the z-index as if you have many sheets of paper on top of another.  Each layer is one above the previous.  Unfortunately it doesn't always work as advertised.  Setting this at 1000 just ensures that it is above all content on the page although it can really be any number greater than zero.&lt;/dd&gt;&lt;dt&gt;-moz-opacity: 0.5&lt;/dt&gt;&lt;dd&gt;This is a special css property that is specific to Mozilla Firefox.  Like any of the other opacity settings: play around with it until it looks how you want it to.&lt;/dd&gt;&lt;dt&gt;opacity: .50&lt;/dt&gt;&lt;dd&gt;This is the default opacity property in css.  Safari uses this.&lt;/dd&gt;&lt;dt&gt;filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50)&lt;/dt&gt;&lt;dd&gt;This whole nonsense is specifically for Internet Explorer 7.  As you can see Microsoft so slyly inserted their name here.&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;
Now you may be thinking, &quot;That's it? We are done? That was so simple!&quot;. If only the world were that simple. We still have to take Internet Explorer 6 into account.&lt;br /&gt;
&lt;br /&gt;
I'm pretty sure if Internet Explorer 6 were a child in elementary school it would be the last kid picked in gym class. Hmmm ... Actually it might be the kid that skipped gym class all together and was in the nurse's office being treated for its terrible diseases.&lt;br /&gt;
&lt;br /&gt;
Anyway, the first thing we have to do is create a stylesheet specifically for IE6. To do that we use a CSS conditional statement in our html like so:&lt;br /&gt;
&lt;div class=&quot;code html&quot;&gt;&amp;lt;!--[if&amp;nbsp;IE&amp;nbsp;6]&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;link&amp;nbsp;href=&lt;span class=&quot;_string&quot;&gt;&amp;quot;overlay_ie6.css&amp;quot;&lt;/span&gt;&amp;nbsp;rel=&lt;span class=&quot;_string&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt;&amp;nbsp;type=&lt;span class=&quot;_string&quot;&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&amp;nbsp;/&amp;gt;&lt;span class=&quot;_default&quot;&gt;&lt;br /&gt;&lt;/span&gt;&amp;lt;![endif]--&amp;gt;&lt;/div&gt;&lt;br /&gt;
Now inside of overlay_ie6.css we add the following styles:&lt;br /&gt;
&lt;div class=&quot;code css&quot;&gt;&lt;span class=&quot;_method&quot;&gt;#overlay&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;absolute&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;filter&lt;/span&gt;:&amp;nbsp;alpha(opacity=&lt;span class=&quot;_int&quot;&gt;50&lt;/span&gt;);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
This is because IE6 does not like position: fixed or the Microsoft filter used for IE7. Therefore we must do this so that it will begin to play nicely. The final step is adding a few lines of Javascript only for IE6. I am using jQuery cause it is my framework of choice and is very speedy and light weight. This is definitely a hack, and I do not really like hacks so if anyone has come across this problem before and has a more elegant solution I urge you to leave me a comment.&lt;br /&gt;
&lt;div class=&quot;code javascript&quot;&gt;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(jQuery&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;browser&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;msie&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;jQuery&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;browser&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;version&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;6&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;var&lt;/span&gt;&amp;nbsp;width&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_class&quot;&gt;window&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;width();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;var&lt;/span&gt;&amp;nbsp;height&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_class&quot;&gt;window&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;height();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;var&lt;/span&gt;&amp;nbsp;pageHeight&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_class&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;clientHeight;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(pageHeight&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;height)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;pageHeight;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;&amp;quot;#overlay&amp;quot;&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;css({width:&amp;nbsp;width,&amp;nbsp;height:&amp;nbsp;height});&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
This code is fairly straight forward, but basically what it is doing is figuring out a pixel width and pixel height to set the overlay to for IE6. IE6 does not like using percentages in this case. First we get the height and width of the current window. Then we get the height of the window with content (assuming all of the horizontal content fits within the width of the window - no side scrolling). Whichever height is greater is the height we use at the end to explicitly set the height and width of the #overlay div.&lt;br /&gt;
&lt;br /&gt;
That's all for now!&lt;br /&gt;
&lt;br /&gt;
</description><pubDate>Thu, 12 Mar 2009 02:56:24 +0000</pubDate><guid>15</guid><author>Craig Campbell</author></item><item><title>Syntax Highlighting For Your Blog Using TextMate!</title><link>http://www.craigiam.com/blog/syntax-highlighting-for-your-blog-using-textmate/14</link><description>I dare anyone to tell me a better way to spend the evening after an 11 hour workday staring at code than writing a blogpost about code. Haha, you'll have to forgive me if any of my writing seems scatterbrained that is most likely because my head is spinning like one of those amusement park rides that goes completely upside down and then stays there for 10 seconds before moving again.&lt;br /&gt;
&lt;br /&gt;
Anyway I have only written a couple serious posts here and already I have had a few people ask me how I did my syntax highlighting. It is no secret online syntax highlighting solutions are not super amazing. They are pretty good, sure, but not awesome. That is where &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/TextMate&quot;&gt;TextMate&lt;/a&gt; comes in. TextMate has a little known feature found in the Bundles menu under TextMate: Create HTML From Document.&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&quot;http://uploads.craigiam.com/img/w604_h_c_r/yBrTDjXy.jpg&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
That's it! Well not quite. The HTML TextMate generates is not perfect. For one it uses the &lt;span class=&quot;code&quot;&gt;&amp;lt;pre&amp;gt;&lt;/span&gt; tag which has been deprecated in XHTML 1.0 Strict. To fix that is easy just replace &amp;lt;pre&amp;gt; with &amp;lt;div&amp;gt; in the html as well as the styles. The next thing to do is move your styles out into their own stylesheet. One bizarre thing is that any user generated colours will appear in your stylesheet in the format &lt;span class=&quot;code&quot;&gt;color: rgba(255, 0, 9, 0.87);&lt;/span&gt; which will not work in Internet Explorer so you'll have to convert those to their hex values.&lt;br /&gt;
&lt;br /&gt;
Also removing the &lt;span class=&quot;code&quot;&gt;&amp;lt;pre&amp;gt;&lt;/span&gt; tag will break the code in Internet Explorer:&lt;br /&gt;
&lt;div class=&quot;code css&quot;&gt;&lt;span class=&quot;_method&quot;&gt;pre&lt;span class=&quot;_int&quot;&gt;.&lt;/span&gt;textmate-source&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;padding&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-family&lt;/span&gt;:&amp;nbsp;Monaco,&amp;nbsp;monospace;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line-height&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1.3&lt;/span&gt;em;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;word-wrap&lt;/span&gt;:&amp;nbsp;break-word;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space&lt;/span&gt;:&amp;nbsp;pre;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space&lt;/span&gt;:&amp;nbsp;pre-wrap;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space&lt;/span&gt;:&amp;nbsp;-moz-pre-wrap;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space&lt;/span&gt;:&amp;nbsp;-o-pre-wrap;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
The fix is super simple, however. This is the one I am using on this site:&lt;br /&gt;
&lt;div class=&quot;code css&quot;&gt;&lt;span class=&quot;_method&quot;&gt;&lt;span class=&quot;_int&quot;&gt;.&lt;/span&gt;textmate-source&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-top&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;30&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-bottom&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;30&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-family&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;Monaco&amp;quot;&lt;/span&gt;,&amp;nbsp;monospace;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;11.5&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line-height&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;1.3&lt;/span&gt;em;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;word-wrap&lt;/span&gt;:&amp;nbsp;break-word;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;white-space&lt;/span&gt;:&amp;nbsp;pre;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;_method&quot;&gt;&lt;span class=&quot;_int&quot;&gt;.&lt;/span&gt;limit-height&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;&lt;span class=&quot;_int&quot;&gt;400&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;px&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;_class&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;overflow&lt;/span&gt;:&amp;nbsp;scroll;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
I added the extra margin in there just to give it some breathing room. Also if you want to make a scrollable box you can just add the &quot;limit-height&quot; class to the main div that holds your code. Another thing to note is that for some reason the &quot;line-num&quot; span class is in single quotes. It still validates, but you might as well make it double quotes for consistency. I am probably forgetting something, but I can barely keep my eyes open at the moment so I will add it if I think of it, but yeah very cool. Enjoy!</description><pubDate>Thu, 26 Feb 2009 05:37:34 +0000</pubDate><guid>14</guid><author>Craig Campbell</author></item><item><title>Cool Object Building With PHP</title><link>http://www.craigiam.com/blog/cool-object-building-with-php/13</link><description>At work I write mostly &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; code and work among some very respected developers in the PHP community. One thing that bothers me about the PHP world is how most people think in terms of &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Array&quot;&gt;arrays&lt;/a&gt; instead of in terms of &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Object_(computer_science)&quot;&gt;objects&lt;/a&gt;. This is understandable considering &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Object-oriented_programming&quot;&gt;Object Oriented&lt;/a&gt; PHP didn't really come around until PHP 5 so using arrays is probably an old habit that is hard to get rid of, but that is no excuse. Arrays have their uses, but I think more often than not an object can be used instead.&lt;br /&gt;
&lt;br /&gt;
One of the core problems most PHP developers run into is finding a way to map records in the database to PHP objects. This is understandable considering your database model is often very different from your object model, and at the moment PHP does not offer any great solutions that I know of. Basically my proposal involves two parts:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;a &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Data_Access_Object&quot;&gt;DAO&lt;/a&gt; (data access object) class&lt;/li&gt;&lt;li&gt;a Builder class&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;
What these classes do is very simple: The DAO contains the &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/SQL&quot;&gt;SQL&lt;/a&gt; to query the database and then calls a builder to take the resulting array and assemble an object (or a collection of objects) out of it which is then returned.&lt;br /&gt;
&lt;br /&gt;
This implementation allows for no question about what is being returned and it forces you to use more objects in your code which is never a bad thing. Another plus is that you can cache the collections directly in &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Memcached&quot;&gt;memcache&lt;/a&gt; and therefore when you hit cache your PHP doesn't have to do any work at all with the data.&lt;br /&gt;
&lt;br /&gt;
This is actually the method I am using on this site so I will demonstrate using real world examples, but before I do so I want to point out that much of the awesomeness in the example relies on a certain naming pattern for your classes. For example I have classes named Blog_Dao, Blog_Comment, Blog_Builder, etc.&lt;br /&gt;
&lt;br /&gt;
The first code I am going to show you is the base DAO class I am using:&lt;br /&gt;
&lt;div class=&quot;code php&quot; style=&quot;height:400px;&quot;&gt;&amp;lt;?php&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;class&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;Dao&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;Db&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_db&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@var&amp;nbsp;Builder&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$_builder&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;constructor&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;sets&amp;nbsp;the&amp;nbsp;database&amp;nbsp;class&amp;nbsp;this&amp;nbsp;dao&amp;nbsp;should&amp;nbsp;use&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;__construct&lt;/span&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_db&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Db&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;determines&amp;nbsp;what&amp;nbsp;builder&amp;nbsp;class&amp;nbsp;to&amp;nbsp;use&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$builder&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;Builder&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;_getBuilder&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$builderName&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;we&amp;nbsp;have&amp;nbsp;already&amp;nbsp;instantiated&amp;nbsp;a&amp;nbsp;builder&amp;nbsp;class&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_keyword&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;_function&quot;&gt;is_null&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_builder))&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_builder;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;we&amp;nbsp;have&amp;nbsp;not&amp;nbsp;passed&amp;nbsp;in&amp;nbsp;a&amp;nbsp;specific&amp;nbsp;builder&amp;nbsp;to&amp;nbsp;use&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_function&quot;&gt;is_null&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$builderName&lt;/span&gt;))&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builderName&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;str_replace&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;'_Dao'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'_Builder'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;get_class&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;make&amp;nbsp;sure&amp;nbsp;the&amp;nbsp;builder&amp;nbsp;exists&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_keyword&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;_function&quot;&gt;class_exists&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$builderName&lt;/span&gt;))&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Exception&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$builderName&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'&amp;nbsp;does&amp;nbsp;not&amp;nbsp;exist!'&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;instantiate&amp;nbsp;the&amp;nbsp;builder&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_builder&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builderName&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_builder;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;calls&amp;nbsp;the&amp;nbsp;builder&amp;nbsp;to&amp;nbsp;build&amp;nbsp;a&amp;nbsp;collection&amp;nbsp;of&amp;nbsp;the&amp;nbsp;stuff&amp;nbsp;returned&amp;nbsp;from&amp;nbsp;the&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;dao!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;mixed&amp;nbsp;$records&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$builder&amp;nbsp;name&amp;nbsp;of&amp;nbsp;class&amp;nbsp;to&amp;nbsp;use&amp;nbsp;for&amp;nbsp;building&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;Collection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;_buildCollection&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builder&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;null&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;the&amp;nbsp;database&amp;nbsp;doesn't&amp;nbsp;have&amp;nbsp;any&amp;nbsp;records&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$collection&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Collection&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;as&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$collection&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;append(&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_buildOne(&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builder&lt;/span&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$collection&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;calls&amp;nbsp;the&amp;nbsp;builder&amp;nbsp;and&amp;nbsp;builds&amp;nbsp;a&amp;nbsp;single&amp;nbsp;object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;mixed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$builder&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;Object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;_buildOne&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builder&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;null&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;//&amp;nbsp;if&amp;nbsp;the&amp;nbsp;database&amp;nbsp;doesn't&amp;nbsp;have&amp;nbsp;any&amp;nbsp;record&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;false&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builder&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_getBuilder(&lt;span class=&quot;_variable&quot;&gt;$builder&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$builder&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;assemble(&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
The first thing you will probably notice is that $builder is optional! This means you only need to pass in a builder class if the builder is in some wacky place it shouldn't be. So the Blog_Comment_Dao class will default to the Blog_Comment_Builder which makes sense and it forces good use of objects cause it means everything you create a dao for is an object and that DAO should only return things related to that object. Another point of note is the Collection object. This is simply a child of ArrayObject to allow easier access to ArrayObject methods.&lt;br /&gt;
&lt;br /&gt;
Anyway now it is time to see this in action! Here is actual code from this site to get all comments related to a given blog post taken from the Blog_Comment_Dao which extends the base Dao class:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;retrieves&amp;nbsp;all&amp;nbsp;comments&amp;nbsp;for&amp;nbsp;a&amp;nbsp;given&amp;nbsp;blog&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;int&amp;nbsp;$blogId&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;Collection&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;get&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$blogId&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'/*&amp;nbsp;'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_int&quot;&gt;__METHOD__&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;'&amp;nbsp;*/'&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;SELECT&amp;nbsp;bc.id&amp;nbsp;id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bc.name&amp;nbsp;name,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bc.website&amp;nbsp;website,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bc.email&amp;nbsp;email,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bc.body&amp;nbsp;body,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bc.posted_on&amp;nbsp;posted_on&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;blog_comment&amp;nbsp;bc&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;bc.blog_id&amp;nbsp;=&amp;nbsp;:blog_id&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_db&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;prepare(&lt;span class=&quot;_variable&quot;&gt;$query&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;bindValue(&lt;span class=&quot;_string&quot;&gt;':blog_id'&lt;/span&gt;,&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$blogId&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;execute();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$sth&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;fetchAllAssoc();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;_buildCollection(&lt;span class=&quot;_variable&quot;&gt;$records&lt;/span&gt;);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
Look how pretty that is! Now let's take a look at the Blog_Comment_Builder class to see how simple that is as well:&lt;br /&gt;
&lt;div class=&quot;code php&quot;&gt;&amp;lt;?php&lt;br /&gt;&lt;span class=&quot;_keyword&quot;&gt;class&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;Blog_Comment_Builder&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_comment&quot;&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;creates&amp;nbsp;a&amp;nbsp;comment&amp;nbsp;object&amp;nbsp;from&amp;nbsp;database&amp;nbsp;record&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;Blog_Comment&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_method&quot;&gt;assemble&lt;/span&gt;(&lt;span class=&quot;_function&quot;&gt;array&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Blog_Comment&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;name&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'name'&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;website&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'website'&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;email&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'email'&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;body&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'body'&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;_keyword&quot;&gt;&amp;gt;&lt;/span&gt;postedOn&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_function&quot;&gt;Date&lt;/span&gt;(&lt;span class=&quot;_variable&quot;&gt;$record&lt;/span&gt;[&lt;span class=&quot;_string&quot;&gt;'posted_on'&lt;/span&gt;]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;return&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_variable&quot;&gt;$comment&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
Something to note here is that these are not public &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Property_(programming)&quot;&gt;properties&lt;/a&gt;. They are all protected, but each domain object extends a Domain_Object class that has magic __set() and __get() methods so you don't have to write setters and getters for every single property in every single class! For more on that check out &lt;a rel=&quot;external&quot; href=&quot;http://codenaked.org/archives/7-Object-Property-Visibility-and-Magic-Methods.html&quot;&gt;this post&lt;/a&gt; by Matthew Purdon.&lt;br /&gt;
&lt;br /&gt;
You can see that properties of objects can still be other objects such as the Date class here. In the case where you are showing a bunch of Users on your site and each one has a bunch of other classes associated it with it you probably wouldn't want to use the other class's builders because then you end up running queries in loops which is never a good thing. Instead you can handle that logic in the User_Builder cause at the end of the day even if there are other classes involved the Builder is just returning one object from one database record.&lt;br /&gt;
&lt;br /&gt;
An obvious downfall here, of course, is that every object needs to have its own Builder class even though the builder seems like something that could happen automatically if there was better &lt;a rel=&quot;external&quot; href=&quot;http://en.wikipedia.org/wiki/Object-relational_mapping&quot;&gt;ORM&lt;/a&gt; support in PHP or any for that matter. This is something that PHP developers are used to, however, because no matter what framework you use, you still end up having to write tons of code to do even simple operations. Hopefully this will make your life easier.</description><pubDate>Tue, 24 Feb 2009 05:16:32 +0000</pubDate><guid>13</guid><author>Craig Campbell</author></item><item><title>Internet Explorer Ajax Requests Using GET</title><link>http://www.craigiam.com/blog/internet-explorer-ajax-requests-using-get/12</link><description>So after getting this page up and running I had to do my fair share of debugging to make things work with Internet Explorer. This is the part of the day that every web developer dreams about. &quot;What is going to break this time??&quot;.&lt;br /&gt;
&lt;br /&gt;
Anyway I decided to use my blog to share with you all solutions to problems I have come across so that you don't have to spend hours banging your head against the wall like I did.&lt;br /&gt;
&lt;br /&gt;
The first topic I want to discuss in this series is ajax calls using &lt;strong&gt;GET&lt;/strong&gt;.&lt;br /&gt;
&lt;br /&gt;
To start I will paste to you the definition of &lt;strong&gt;GET&lt;/strong&gt; from the World Wide Web Consortium&lt;br /&gt;
&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;GET&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The &lt;strong&gt;GET&lt;/strong&gt; method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process.&lt;/p&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;
&lt;br /&gt;
Basically &lt;strong&gt;GET&lt;/strong&gt; shows you what you should see based on the URI you request. For example on Facebook every user has their own profile defined by /profile.php?id=1234567 where the number following the &amp;#61 is your user id in the database.&lt;br /&gt;
&lt;br /&gt;
Really &lt;strong&gt;GET&lt;/strong&gt; should be used for just that: determining what to show you. Facebook uses &lt;strong&gt;GET&lt;/strong&gt; to track things. Yes, Facebook tracks almost everything you do. For example when you go to the home page you will see &amp;amp;ref=logo or &amp;amp;ref=home in the URL depending on which link you clicked on. Facebook even attaches your user id to the url when you view another user's photos. This means they can find all the hotties that people look at pictures of the most, but that is a story for another time.&lt;br /&gt;
&lt;br /&gt;
So you might wonder where I am going with this... On this site I set it up so blog comments are posted and retrieved with AJAX calls. This means the page doesn't have to refresh when you post a comment. Everything seemed great until I tried posting a comment on Internet Explorer. No matter how many times I refreshed the page I couldn't get my comment to show up. Does this mean it isn't being added to the database? Does this mean the AJAX call is not firing? No and no. What this means is that Internet Explorer caches AJAX requests made using GET.&lt;br /&gt;
&lt;br /&gt;
For many things this would be fine like a page that is all static content, but for something like blog comments they are changing all the time (not on this site, however) this is unacceptable.&lt;br /&gt;
&lt;br /&gt;
So there are a few ways to solve this problem including changing all requests to be &lt;strong&gt;POST&lt;/strong&gt;. I opted to pass the current timestamp along in the URL. This tricks Internet Explorer into thinking that it is a page that has never been accessed before and you will receive the correct response :).&lt;br /&gt;
&lt;br /&gt;
Here is the code (note I use JQuery for all my javascripts):&lt;br /&gt;
&lt;div class=&quot;code javascript&quot;&gt;&lt;span class=&quot;_method&quot;&gt;getComments&amp;nbsp;&lt;/span&gt;:&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;var&lt;/span&gt;&amp;nbsp;timestamp&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;=&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;new&lt;/span&gt;&amp;nbsp;Date()&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;getTime();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;get(wwwUrl&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;/ajax/blog/get-comments?blogId=&amp;quot;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;id&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_string&quot;&gt;&amp;quot;&amp;amp;timestamp=&amp;quot;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;+&lt;/span&gt;&amp;nbsp;timestamp,&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;function&lt;/span&gt;(html)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;_keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;_string&quot;&gt;&amp;quot;#comments&amp;quot;&lt;/span&gt;)&lt;span class=&quot;_default&quot;&gt;.&lt;/span&gt;html(html);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;
As you can see it is super simple. new Date().getTime(); returns the current UNIX timestamp in milliseconds so we get up to date comments! Go ahead and leave one to try it for yourself</description><pubDate>Sun, 22 Feb 2009 23:33:11 +0000</pubDate><guid>12</guid><author>Craig Campbell</author></item></channel></rss>
