<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Tower Of Power</title>
	<atom:link href="http://www.toosweettobesour.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.toosweettobesour.com</link>
	<description>Far Too Sweet To Be Sour</description>
	<pubDate>Wed, 23 Jul 2008 20:37:52 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>[Net Perspective Cross Post] Time is Money: Save Time With Automation And Phing</title>
		<link>http://www.toosweettobesour.com/2008/07/23/net-perspective-cross-post-time-is-money-save-time-with-automation-and-phing/</link>
		<comments>http://www.toosweettobesour.com/2008/07/23/net-perspective-cross-post-time-is-money-save-time-with-automation-and-phing/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 16:59:36 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=69</guid>
		<description><![CDATA[(Originally posted on my company's blog)
I've been talking a lot about automation as of late and posted a generic, overload broad view of the tools and utilities I use here at Net Perspective. However, I wanted to go into detail about my real world uses of a particular tool, Phing.
In my time with Net Perspective [...]]]></description>
			<content:encoded><![CDATA[<p><strong>(Originally posted on <a href="http://blog.net-perspective.com/2008/07/23/time-is-money-save-time-with-automation/">my company's blog</a>)</strong></p>
<p class="lead">I've been talking a lot about automation as of late and <a href="http://www.toosweettobesour.com/2008/05/15/automating-the-development-workflow/">posted</a> a generic, overload broad view of the tools and utilities I use here at Net Perspective. However, I wanted to go into detail about my real world uses of a particular tool, <a href="http://phing.info/">Phing</a>.</p>
<p>In my time with <a href="http://www.net-perspective.com/">Net Perspective</a> (and our previous existence), I've completely dreaded live deployment days, and yes they were full days. An entire day dedicated to waiting for FTP to finish uploads, chmod'ing directories (because Plesk hates me), setting up databases, and testing. All of this despite the fact that we did periodic staging deployments on the same server!</p>
<p>I guess a lot of thanks goes out to <a href="http://www.amazon.com/Pro-PHP-Patterns-Frameworks-Testing/dp/1590598199">Pro PHP: Patterns, Frameworks, Testing, and More</a> by Kevin McArthur. While I found this book to feel more like a Zend Framework tutorial, it did provide a brief introduction to 2 utilities I use here at work, only one of which we care about at the moment: <a href="http://phing.info/">Phing</a>.</p>
<p>Phing is a build environment based on Ant (familiar to those in Java world). For those not familiar, Phing uses XML based build files with tags representing tasks and task groupings. At Net Perspective, I use Phing build scripts for everything from packaging up tarballs of utilities we've published (simple jQuery plug-ins, etc.) to <em>automating the live deployment of client sites</em>. The latter I'm particularly happy with as my deployment time has been reduced from a few hours between 10 minutes max (for a brand new, fresh upload) and about 30 seconds (for an update).</p>
<p>Basic Phing usage is pretty self explanatory, however you may wish to search Google for Phing tutorials, or read my post I linked above.</p>
<p>Further more, my build scripts make use of custom command executions requiring both the execution environment to be *NIX based and for you to read <a href="http://troy.jdmz.net/rsync/index.html">this article</a> on using rsync over ssh without a password (using pre-shared keys).</p>
<p><a href="http://blog.net-perspective.com/2008/07/23/time-is-money-save-time-with-automation/">Read the rest of my post here...</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/07/23/net-perspective-cross-post-time-is-money-save-time-with-automation-and-phing/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP 5.3 and Closures</title>
		<link>http://www.toosweettobesour.com/2008/07/21/php-53-and-closures/</link>
		<comments>http://www.toosweettobesour.com/2008/07/21/php-53-and-closures/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 19:28:06 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=62</guid>
		<description><![CDATA[I'm fairly excited because as of only a week or so ago I found the closures rfc, and not only did I find that the rfc has a working patch, apparently it's already in PHP 5.3.
You see, apparently it's not good enough that we get name spaces and late static binding, oh no, we get [...]]]></description>
			<content:encoded><![CDATA[<p>I'm fairly excited because as of only a week or so ago I found the <a href="http://wiki.php.net/rfc/closures">closures rfc</a>, and not only did I find that the rfc has a working patch, apparently it's already in PHP 5.3.</p>
<p>You see, apparently it's not good enough that we get name spaces and late static binding, oh no, we get closures too!</p>
<p>I downloaded the Win32 snapshot from <a href="http://snaps.php.net/">PHP snapshots page</a> and indeed, closure support was included.</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #0000ff;">$closure</span> = <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$args</span><span style="color: #66cc66;">&#41;</span> use <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$global</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">/*Body*/</span> <span style="color: #66cc66;">&#125;</span>;
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;</pre>
<p>According to the rfc, one must manually define external variables used within a function, however in my own tests you can still use the <code>global</code> keyword. The difference between the two is the <code>use</code> statement preserves the value of <code>$global</code> at creation and the <code>global</code> keyword would work as you would expect it to with a normal function. For example:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #0000ff;">$global</span> = <span style="color: #ff0000;">&quot;Global Variable&quot;</span>;
&nbsp;
<span style="color: #0000ff;">$closureUse</span> = <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$arg</span><span style="color: #66cc66;">&#41;</span> use <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$global</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$global</span> . <span style="color: #ff0000;">&quot; - &quot;</span> . <span style="color: #0000ff;">$arg</span>; <span style="color: #66cc66;">&#125;</span>;
<span style="color: #0000ff;">$closureGlobal</span> = <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$arg</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.php.net/global"><span style="color: #000066;">global</span></a> <span style="color: #0000ff;">$global</span>; <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$global</span> . <span style="color: #ff0000;">&quot; - &quot;</span> . <span style="color: #0000ff;">$arg</span>; <span style="color: #66cc66;">&#125;</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Basic Closure Tests<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;-------------------<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>closureUse('test'): &quot;</span>;
<span style="color: #0000ff;">$closureUse</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'test'</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>closureGlobal('test'): &quot;</span>;
<span style="color: #0000ff;">$closureGlobal</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'test'</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Global Closure Tests<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;--------------------<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<span style="color: #0000ff;">$global</span> = <span style="color: #ff0000;">&quot;Global Variable (Changed)&quot;</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>closureUse('test') (changed <span style="color: #000099; font-weight: bold;">\$</span>global): &quot;</span>;
<span style="color: #0000ff;">$closureUse</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'test'</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>closureGlobal('test') (changed <span style="color: #000099; font-weight: bold;">\$</span>global): &quot;</span>;
<span style="color: #0000ff;">$closureGlobal</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'test'</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;</pre>
<p>Would output:</p>
<pre class="text">&nbsp;
Basic Closure Tests
-------------------
&nbsp;
$closureUse('test'): Global Variable - test
$closureGlobal('test'): Global Variable - test
&nbsp;
Global Closure Tests
--------------------
&nbsp;
$closureUse('test') (changed $global): Global Variable - test
$closureGlobal('test') (changed $global): Global Variable (Changed) - test
&nbsp;</pre>
<p>You can, as well, return references with a closure by putting the & between the function keyword and the parenthesis.</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #0000ff;">$closureReturnsReference</span> = <span style="color: #000000; font-weight: bold;">function</span> &amp; <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$args</span><span style="color: #66cc66;">&#41;</span> use <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$global</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">/*Body*/</span> <span style="color: #66cc66;">&#125;</span>;
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;</pre>
<p>Just one of many shiny fancy things to look forward to in PHP 5.3.</p>
<h3>Edit 7/23/2008:</h3>
<p>I should mention to the people that trashed my examples on reddit, I'm sorry for assuming you knew  what closures were and the the real world uses of them. I will try to refrain from giving a concise example of how a new language feature interacts with existing features and conventions, especially in PHP where things are a bit disorganized.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/07/21/php-53-and-closures/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Updates</title>
		<link>http://www.toosweettobesour.com/2008/07/08/updates/</link>
		<comments>http://www.toosweettobesour.com/2008/07/08/updates/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 22:52:20 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=61</guid>
		<description><![CDATA[I apologize about the month without updates. Our business manager and lead designer ("Director of Operations" and "Creative Director") both had to go to the hospital at about the same time and the shortest stay was almost 2 weeks. They both pulled through just fine and everything is back to normal.
I hope to be back [...]]]></description>
			<content:encoded><![CDATA[<p>I apologize about the month without updates. Our business manager and lead designer ("Director of Operations" and "Creative Director") both had to go to the hospital at about the same time and the shortest stay was almost 2 weeks. They both pulled through just fine and everything is back to normal.</p>
<p>I hope to be back sometime later this week with some visible signs of awesomeness on a side project of mine.</p>
<p>In the mean time I've been playing with Flex Builder 3 (hooray for free Educational licenses) and while it's cool, so far the documentation is hindering my development efforts. I have a project planned where I intend to have an AIR client and am evaluating using Flex instead of HTML+JavaScript. We'll see how far that goes.</p>
<p>And finally I've been playing around with <a href="http://friendfeed.com/dcousineau">FriendFeed</a> and have an account setup. I, for one, welcome our new stalker overlords.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/07/08/updates/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Laziness Makes A Great Developer</title>
		<link>http://www.toosweettobesour.com/2008/06/09/laziness-makes-a-great-developer/</link>
		<comments>http://www.toosweettobesour.com/2008/06/09/laziness-makes-a-great-developer/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 06:26:54 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=58</guid>
		<description><![CDATA[One of the guiding principles I have lived by the came from my middle school swimming coach. He told us:
Don't do more work than you have to.
On first glance, it doesn't seem to be very good advice. However when you realize that what he was getting at was we shouldn't waste energy on a poor [...]]]></description>
			<content:encoded><![CDATA[<p>One of the guiding principles I have lived by the came from my middle school swimming coach. He told us:</p>
<blockquote><p>Don't do more work than you have to.</p></blockquote>
<p>On first glance, it doesn't seem to be very good advice. However when you realize that what he was getting at was we shouldn't waste energy on a poor stroke, the quote takes on a much deeper and more profound meaning. It is this principle that takes a good developer and makes him great.</p>
<h3>Profile of a Good Developer</h3>
<p>Good developers are almost a dime a dozen. Walk in to any computer science course or <a href="http://www.net-perspective.com/">web development</a> shop and you'll find that the majority, if not all, are good developers.</p>
<p>These "good" developers can sit down and work through an object oriented architecture, they can construct their SQL queries, and can write an application that just works.</p>
<p>A "good" developer checks in his source code at the proper times, he comments his code as well as could be expected, and you can usually be guaranteed his code will compile and execute with very little fuss.</p>
<h3>Profile of a GREAT Developer</h3>
<p>What separates the great developers from the good developers is LAZINESS! You will find that the good developers, while producing clean, working code, operate much slower than great developers, and for the reason that separates the good from the great.</p>
<p>Good developers are set in their ways of just manually working with everything. A good developer handles deployment with FTP, and updates database structure by hand. In the end, the good developer ends up wasting time doing menial tasks. FTP alone can kill up to 30 minutes of your day. Good developers are very set in their ways and do not like new things introduced.</p>
<p>Meanwhile GREAT developers <strong>HATE</strong> menial tasks. They abhor having to drop into the console every time they wish to test or deploy, and loath dropping into the database to manually update structure. So these GREAT developers begin to write scripts and integrate all their tools to reduce their menial overhead as much as possible.</p>
<p>The GREAT developer is lazy because they do not want to do things themselves, so they spend 20 minutes automating their tasks so they'll never deal with it again. And when you think about it, when you could spend 20 minutes once writing automated deploy scripts but instead spend 20 minutes every deploy in FTP, you are <em>doing more work than you have to</em>.</p>
<h3>What Does This Mean For Me?</h3>
<p>All of us developers should strive to be as lazy as possible. Do you have a task you have to do more than 3 times total? Write a script or a <a href="http://www.phing.info/">build task</a> for it. Do you spend a lot of time testing features? <a href="http://www.phpunit.de/">Automate your testing</a>. And if possible, <a href="http://www.xinc.eu/">integrate the systems</a> so you never even have to run those scripts manually, reducing user intervention to one step.</p>
<p>I know I try to be as lazy as possible, do you?</p>
<p><strong>Edit 6/10/2008:</strong></p>
<p>I feel I should make sure everyone knows that I am to an extent being facetious with the word "laziness" but I'm being completely serious on the "don't do more work than you have to." While a good developer can handle long, arduous tasks that are prone to human error, a great developer avoids them in the first place.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/06/09/laziness-makes-a-great-developer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Updates To Come</title>
		<link>http://www.toosweettobesour.com/2008/06/07/updates-to-come/</link>
		<comments>http://www.toosweettobesour.com/2008/06/07/updates-to-come/#comments</comments>
		<pubDate>Sun, 08 Jun 2008 01:04:56 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=57</guid>
		<description><![CDATA[I'm currently out for the weekend, brother's graduated high school!
When I get back I've got some updates for the hierarchical data post, and should have a post ready on using rsync and phing for remote deployment.
]]></description>
			<content:encoded><![CDATA[<p>I'm currently out for the weekend, brother's graduated high school!</p>
<p>When I get back I've got some updates for the <a href="http://www.toosweettobesour.com/2008/06/02/hierarchical-data-with-php-and-mysql/">hierarchical data post</a>, and should have a post ready on using rsync and phing for remote deployment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/06/07/updates-to-come/feed/</wfw:commentRss>
		</item>
		<item>
		<title>10 Hours With Plurk</title>
		<link>http://www.toosweettobesour.com/2008/06/02/10-hours-with-plurk/</link>
		<comments>http://www.toosweettobesour.com/2008/06/02/10-hours-with-plurk/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 04:28:53 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Social Networking]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=56</guid>
		<description><![CDATA[So I now have spent about 10 hours on Plurk.
About an hour of those 10 I spent OFF the service.
It is officially addicting.
]]></description>
			<content:encoded><![CDATA[<p>So I now have spent about 10 hours on <a href="http://plurk.com/redeemByURL?from_uid=17206&check=-1542535855&s=1">Plurk</a>.</p>
<p>About an hour of those 10 I spent OFF the service.</p>
<p>It is officially addicting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/06/02/10-hours-with-plurk/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Plurk: Even worse than twitter!</title>
		<link>http://www.toosweettobesour.com/2008/06/02/plurk-even-worse-than-twitter/</link>
		<comments>http://www.toosweettobesour.com/2008/06/02/plurk-even-worse-than-twitter/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 19:58:29 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Social Networking]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=55</guid>
		<description><![CDATA[So whurley pointed me towards plurk earlier today.
Naturally I join because (a) I'm a natural sucker, and (b) being a geek I join just about every service to check it out.
To give a brief rundown, plurk is another microblogging service just like twitter only it focuses on the social networking aspect a bit more than [...]]]></description>
			<content:encoded><![CDATA[<p>So <a href="http://whurley.com/">whurley</a> pointed me towards <a href="http://plurk.com/redeemByURL?from_uid=17206&check=-1542535855&s=1">plurk</a> earlier today.</p>
<p>Naturally I join because (a) I'm a natural sucker, and (b) being a geek I join just about every service to check it out.</p>
<p>To give a brief rundown, plurk is another microblogging service just like <a href="http://twitter.com/">twitter</a> only it focuses on the social networking aspect a bit more than twitter, its currently more responsive than twitter (but that will change as plurk starts experiencing heavy load), and it has a really nifty timeline interface (by the way, plurk guys: we're all kinda used to reading a timeline from right-to-left, not left-to-right).</p>
<p>I would highly suggest people <a href="http://plurk.com/redeemByURL?from_uid=17206&check=-1542535855&s=1">join up and check it out</a>, if for anything to boost my karma points and waste the time in your day you weren't going to spend on something useful in the first place.</p>
<p>Oh and for you first time users, check out <a href="http://plurk.ryanlim.com/help/">The Unofficial Guide To Plurk</a> to get the help that is so woefully inadequate on the official plurk website.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/06/02/plurk-even-worse-than-twitter/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Hierarchical Data With PHP and MySQL</title>
		<link>http://www.toosweettobesour.com/2008/06/02/hierarchical-data-with-php-and-mysql/</link>
		<comments>http://www.toosweettobesour.com/2008/06/02/hierarchical-data-with-php-and-mysql/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 07:28:38 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=54</guid>
		<description><![CDATA[I recently had fun with an all-to-common issue with SQL driven websites: hierarchical data. For those who don't like big words, think trees. Other people have already discussed storage methods, and I would actually highly suggest you read the writeup if you haven't already.
While it is fairly straightforward to deal with, in our case we [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had fun with an all-to-common issue with SQL driven websites: hierarchical data. For those who don't like big words, think trees. <a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">Other people</a> have already discussed storage methods, and I would actually highly suggest you read the writeup if you haven't already.</p>
<p>While it is fairly straightforward to deal with, in our case we use <a href="http://pear.php.net/package/HTML_QuickForm">HTML_QuickForm</a> to handle our forms and are using QuickForm's <a href="http://pear.php.net/manual/en/package.html.html-quickform.html-quickform-hierselect.setoptions.php">hierselect</a> to select a category.</p>
<p>The issue starts showing its face in 2 distinct areas: (1) the client is not yet sure how deep they need their categories to go, and (2) the hierselect requires a very specific format of data to be passed in.</p>
<p><span id="more-54"></span></p>
<p>To start off we have our categories table:</p>
<pre class="sql">&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span>  <span style="color: #ff0000;">`categories`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>,
  <span style="color: #ff0000;">`parent_id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span>,
  <span style="color: #ff0000;">`title`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span>,
  <span style="color: #ff0000;">`active`</span> tinyint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'1'</span>,
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>,
  <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #ff0000;">`fk_categories_categories`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">&#41;</span>,
  CONSTRAINT <span style="color: #ff0000;">`fk_categories_categories`</span> <span style="color: #993333; font-weight: bold;">FOREIGN</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">REFERENCES</span> <span style="color: #ff0000;">`categories`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #993333; font-weight: bold;">DELETE</span> NO ACTION <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #993333; font-weight: bold;">UPDATE</span> NO ACTION
<span style="color: #66cc66;">&#41;</span> ENGINE=InnoDB <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET=latin1;
&nbsp;</pre>
<p>To make life easier for myself I have my model auto generating the SQL statement to go n levels deep in printing all categories:</p>
<pre class="php">&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/intval"><span style="color: #000066;">intval</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$depth</span><span style="color: #66cc66;">&#41;</span> &lt; <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #0000ff;">$depth</span> = <span style="color: #cc66cc;">1</span>;
&nbsp;
<span style="color: #0000ff;">$select</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$from</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$where</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$order</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$i</span> = <span style="color: #cc66cc;">1</span>; <span style="color: #0000ff;">$i</span> &lt;= <span style="color: #0000ff;">$depth</span>; <span style="color: #0000ff;">$i</span>++ <span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #0000ff;">$select</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">&quot;level&quot;</span> . <span style="color: #0000ff;">$i</span> . <span style="color: #ff0000;">&quot;.id AS level&quot;</span> . <span style="color: #0000ff;">$i</span> . <span style="color: #ff0000;">&quot;_id&quot;</span>;
	<span style="color: #0000ff;">$from</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">&quot;`categories` AS level&quot;</span> . <span style="color: #0000ff;">$i</span> . <span style="color: #ff0000;">&quot;&quot;</span>;
	<span style="color: #0000ff;">$where</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">&quot;( level&quot;</span> . <span style="color: #0000ff;">$i</span> . <span style="color: #ff0000;">&quot;.active = 1 OR level&quot;</span> . <span style="color: #0000ff;">$i</span> . <span style="color: #ff0000;">&quot;.active IS NULL )&quot;</span>;
	<span style="color: #0000ff;">$order</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">&quot;level&quot;</span> . <span style="color: #0000ff;">$i</span> . <span style="color: #ff0000;">&quot;_id&quot;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">//SELECT</span>
<span style="color: #0000ff;">$sql</span> = <span style="color: #ff0000;">&quot;SELECT &quot;</span> . <a href="http://www.php.net/implode"><span style="color: #000066;">implode</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">', '</span>, <span style="color: #0000ff;">$select</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;, level&quot;</span> . <span style="color: #0000ff;">$depth</span> . <span style="color: #ff0000;">&quot;.title AS title &quot;</span> ;
&nbsp;
<span style="color: #808080; font-style: italic;">//FROM</span>
<span style="color: #0000ff;">$sql</span> .= <span style="color: #ff0000;">&quot;FROM &quot;</span> . <span style="color: #0000ff;">$from</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span> . <span style="color: #ff0000;">&quot; &quot;</span>;
&nbsp;
<a href="http://www.php.net/unset"><span style="color: #000066;">unset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$from</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$select</span><span style="color: #66cc66;">&#41;</span> &gt; <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$from</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$key</span> =&gt; <span style="color: #0000ff;">$value</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #0000ff;">$from</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$value</span> . <span style="color: #ff0000;">&quot; ON level&quot;</span> . <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;.id = level&quot;</span> . <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$key</span><span style="color: #cc66cc;">+1</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;.parent_id&quot;</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #0000ff;">$sql</span> .= <span style="color: #ff0000;">&quot; RIGHT JOIN &quot;</span> . <a href="http://www.php.net/implode"><span style="color: #000066;">implode</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot; RIGHT JOIN &quot;</span>, <span style="color: #0000ff;">$from</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot; &quot;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">//WHERE</span>
<span style="color: #0000ff;">$sql</span> .= <span style="color: #ff0000;">&quot;WHERE level1.parent_id IS NULL AND &quot;</span> . <a href="http://www.php.net/implode"><span style="color: #000066;">implode</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot; AND &quot;</span>, <span style="color: #0000ff;">$where</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot; &quot;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">//ORDER</span>
<span style="color: #0000ff;">$sql</span> .= <span style="color: #ff0000;">&quot;ORDER BY &quot;</span> . <a href="http://www.php.net/implode"><span style="color: #000066;">implode</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;, &quot;</span>, <span style="color: #0000ff;">$order</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$rs</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">query</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$sql</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p>At a depth of 5 our SQL query generated becomes:</p>
<pre class="sql">&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span>
  level1.id <span style="color: #993333; font-weight: bold;">AS</span> level1_id,
  level2.id <span style="color: #993333; font-weight: bold;">AS</span> level2_id,
  level3.id <span style="color: #993333; font-weight: bold;">AS</span> level3_id,
  level4.id <span style="color: #993333; font-weight: bold;">AS</span> level4_id,
  level5.id <span style="color: #993333; font-weight: bold;">AS</span> level5_id,
  level5.title <span style="color: #993333; font-weight: bold;">AS</span> title
<span style="color: #993333; font-weight: bold;">FROM</span>
  <span style="color: #ff0000;">`categories`</span> <span style="color: #993333; font-weight: bold;">AS</span> level1
  <span style="color: #993333; font-weight: bold;">RIGHT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`categories`</span> <span style="color: #993333; font-weight: bold;">AS</span> level2 <span style="color: #993333; font-weight: bold;">ON</span> level1.id = level2.parent_id
  <span style="color: #993333; font-weight: bold;">RIGHT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`categories`</span> <span style="color: #993333; font-weight: bold;">AS</span> level3 <span style="color: #993333; font-weight: bold;">ON</span> level2.id = level3.parent_id
  <span style="color: #993333; font-weight: bold;">RIGHT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`categories`</span> <span style="color: #993333; font-weight: bold;">AS</span> level4 <span style="color: #993333; font-weight: bold;">ON</span> level3.id = level4.parent_id
  <span style="color: #993333; font-weight: bold;">RIGHT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`categories`</span> <span style="color: #993333; font-weight: bold;">AS</span> level5 <span style="color: #993333; font-weight: bold;">ON</span> level4.id = level5.parent_id
<span style="color: #993333; font-weight: bold;">WHERE</span>
  level1.parent_id <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span>
  <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> level1.active = <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> level1.active <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> level2.active = <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> level2.active <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> level3.active = <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> level3.active <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> level4.active = <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> level4.active <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> level5.active = <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> level5.active <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span>
  level1_id, level2_id, level3_id, level4_id, level5_id
&nbsp;</pre>
<p>The series of <code>( levelN.active = 1 OR levelN.active IS NULL )</code> guarantees that only entries with the active field turned on and that children of deactivated categories are not displayed. Fancy piece of SQL-fu if I do say so myself. The data is returned looking something like this:</p>
<table border=0 cellspacing=1 cellpadding=1>
<tr>
<th>level1_id</th>
<th>level2_id</th>
<th>level3_id</th>
<th>level4_id</th>
<th>level5_id</th>
<th>title</th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>1</td>
<td>Parent</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>2</td>
<td>Parent 2</td>
</tr>
<td></td>
<td></td>
<td></td>
<td>1</td>
<td>7</td>
<td>Child 2</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td>2</td>
<td>4</td>
<td>Child</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td>2</td>
<td>5</td>
<td>Child 2</td>
</tr>
<tr>
<td></td>
<td></td>
<td>1</td>
<td>6</td>
<td>8</td>
<td>Grandchild</td>
</tr>
<tr>
<td></td>
<td></td>
<td>1</td>
<td>6</td>
<td>9</td>
<td>Grandchild 2</td>
</tr>
<tr>
<td></td>
<td>1</td>
<td>6</td>
<td>8</td>
<td>10</td>
<td>Grandchild</td>
</tr>
<tr>
<td></td>
<td>1</td>
<td>6</td>
<td>8</td>
<td>11</td>
<td>Grandchild 2</td>
</tr>
<tr>
<td>1</td>
<td>6</td>
<td>8</td>
<td>10</td>
<td>12</td>
<td>Great Grandchild</td>
</tr>
<tr>
<td>1</td>
<td>6</td>
<td>8</td>
<td>10</td>
<td>13</td>
<td>Great Grandchild 2</td>
</tr>
</table>
<p><Br /><br />
Now by cleaning up the null values from the $category array we have our path:</p>
<pre class="php">&nbsp;
<span style="color: #0000ff;">$data</span> = <span style="color: #0000ff;">$rs</span>-&gt;<span style="color: #006600;">getRows</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$categories</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$data</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$category</span> <span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #0000ff;">$title</span> = <span style="color: #0000ff;">$category</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'title'</span><span style="color: #66cc66;">&#93;</span>;
	<a href="http://www.php.net/unset"><span style="color: #000066;">unset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$category</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'title'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
	<span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/array_reverse"><span style="color: #000066;">array_reverse</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$category</span>,<span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$key</span> =&gt; <span style="color: #0000ff;">$value</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$value</span> === <span style="color: #000000; font-weight: bold;">null</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<a href="http://www.php.net/unset"><span style="color: #000066;">unset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$category</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	array_set<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$categories</span>, <a href="http://www.php.net/array_merge"><span style="color: #000066;">array_merge</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$category</span><span style="color: #66cc66;">&#41;</span><span style="color: #cc66cc;">-1</span><span style="color: #66cc66;">&#41;</span>,<a href="http://www.php.net/array_values"><span style="color: #000066;">array_values</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$category</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #0000ff;">$title</span>, <span style="color: #ff0000;">&quot;-- SELECT CATEGORY --&quot;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$categories</span>;
&nbsp;</pre>
<p>You'll notice that we also insert into our <code>$categories</code> array according to the hierselect format linked above. That in and of itself is an interesting function as, for example, our entry for Great Great Grandchild would look like <code>$categories[4][1][6][8][10][12] = 'Great Great Grandchild';</code> and we need empty entries for each level.</p>
<p><code>array_set()</code> has this code:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> array_set<span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a> &amp;<span style="color: #0000ff;">$array</span>, <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a> <span style="color: #0000ff;">$keys</span>, <span style="color: #0000ff;">$value</span>, <span style="color: #0000ff;">$emptyText</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #0000ff;">$tmp</span> =&amp; <span style="color: #0000ff;">$array</span>;
&nbsp;
	<span style="color: #0000ff;">$lastKey</span> = <a href="http://www.php.net/array_pop"><span style="color: #000066;">array_pop</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$keys</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$keys</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$key</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/is_array"><span style="color: #000066;">is_array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$tmp</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<span style="color: #0000ff;">$tmp</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#93;</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		<span style="color: #0000ff;">$tmp</span> =&amp; <span style="color: #0000ff;">$tmp</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#93;</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$tmp</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #0000ff;">$tmp</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$emptyText</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #0000ff;">$tmp</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$lastKey</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$value</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>And our final array output will look something like this:</p>
<pre>
Array
(
    [0] => Array
        (
            [] => -- SELECT CATEGORY --
            [1] => Parent
            [2] => Parent 2
        )

    [1] => Array
        (
            [1] => Array
                (
                    [] => -- SELECT CATEGORY --
                    [6] => Child
                    [7] => Child 2
                )

            [2] => Array
                (
                    [] => -- SELECT CATEGORY --
                    [4] => Child
                    [5] => Child 2
                )
        )

    [2] => Array
        (
            [1] => Array
                (
                    [6] => Array
                        (
                            [] => -- SELECT CATEGORY --
                            [8] => Grandchild
                            [9] => Grandchild 2
                        )
                )
        )

    [3] => Array
        (
            [1] => Array
                (
                    [6] => Array
                        (
                            [8] => Array
                                (
                                    [] => -- SELECT CATEGORY --
                                    [10] => Grandchild
                                    [11] => Grandchild 2
                                )
                        )
                )
        )

    [4] => Array
        (
            [1] => Array
                (
                    [6] => Array
                        (
                            [8] => Array
                                (
                                    [10] => Array
                                        (
                                            [] => -- SELECT CATEGORY --
                                            [12] => Great Grandchild
                                            [13] => Great Grandchild 2
                                        )
                                )
                        )
                )
        )
)
</pre>
<p>Good thing is all that needs to be changed to dig deeper into the hierarchy is the <code>$depth</code> variable from above.</p>
<p>This solution is very good for write intensive applications, so anyone building a forum-like system will find use out of this system.</p>
<p>However I'm thinking about moving to the Nested Set model as the application for this code will not be write-intensive...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/06/02/hierarchical-data-with-php-and-mysql/feed/</wfw:commentRss>
		</item>
		<item>
		<title>*AMP and Runaway Scripts</title>
		<link>http://www.toosweettobesour.com/2008/05/21/amp-and-runaway-scripts/</link>
		<comments>http://www.toosweettobesour.com/2008/05/21/amp-and-runaway-scripts/#comments</comments>
		<pubDate>Wed, 21 May 2008 06:56:07 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Apache]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=53</guid>
		<description><![CDATA[Peter Zaitsev posted a very interesting test on how PHP and Apache handle runaway PHP scripts.
I'm sure all of us have had a long executing SQL script or at least a runaway script, and he points out even with ignore_user_abort set to FALSE and max execution times set both in PHP and Apache, a runaway [...]]]></description>
			<content:encoded><![CDATA[<p>Peter Zaitsev <a href="http://www.mysqlperformanceblog.com/2008/05/20/apache-php-mysql-and-runaway-scripts/">posted</a> a very interesting test on how PHP and Apache handle runaway PHP scripts.</p>
<p>I'm sure all of us have had a long executing SQL script or at least a runaway script, and he points out even with <a href="http://www.php.net/manual/en/features.connection-handling.php"><code>ignore_user_abort</code></a> set to FALSE and max execution times set both in PHP and Apache, a runaway SQL query can execute beyond the timeouts, even when aborted by the user (stop button on the browser).</p>
<p>Even using the function <a href="http://www.php.net/connection_aborted"><code>connection_aborted()</code></a> to check for a user abort fails.</p>
<p>However, the script will cease on a user abort if it performs regular <code>ob_flush(); flush();</code>  commands. For example:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Hello&quot;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span>=<span style="color: #cc66cc;">0</span>;<span style="color: #0000ff;">$i</span>&lt;<span style="color: #cc66cc;">10000</span>;<span style="color: #0000ff;">$i</span>++<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<a href="http://www.php.net/sleep"><span style="color: #000066;">sleep</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
	<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'.'</span><span style="color: #66cc66;">&#41;</span>;
	<a href="http://www.php.net/ob_flush"><span style="color: #000066;">ob_flush</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
	<a href="http://www.php.net/flush"><span style="color: #000066;">flush</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>
<p>Just one more reason why I love the <a href="http://www.mysqlperformanceblog.com/">MySql Performance Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/05/21/amp-and-runaway-scripts/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CompizFusion: Blur Your Terminal Window!</title>
		<link>http://www.toosweettobesour.com/2008/05/15/compizfusion-blur-your-terminal-window/</link>
		<comments>http://www.toosweettobesour.com/2008/05/15/compizfusion-blur-your-terminal-window/#comments</comments>
		<pubDate>Thu, 15 May 2008 21:39:10 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=49</guid>
		<description><![CDATA[Messing around with CompizConfig the other day and discovered a nifty tweak: blur your transparent terminal windows!

To do this you need CompizConfig installed:
sudo apt-get install compizconfig-settings-manager
Once installed, go to System > Preferences > Advanced Desktop Effects Settings. Scroll down to Effects and enabled Blur Windows. Then click the Blur Windows button to open the configuration [...]]]></description>
			<content:encoded><![CDATA[<p>Messing around with CompizConfig the other day and discovered a nifty tweak: blur your transparent terminal windows!</p>
<p><a href='http://www.toosweettobesour.com/wp-content/uploads/2008/05/screenshot1.png'><img src="http://www.toosweettobesour.com/wp-content/uploads/2008/05/screenshot1-300x211.png" alt="Blurred Gnome Terminal!" title="Blurred gnome-terminal" width="300" height="211" class="aligncenter size-medium wp-image-50" /></a></p>
<p>To do this you need CompizConfig installed:</p>
<p><code>sudo apt-get install compizconfig-settings-manager</code></p>
<p>Once installed, go to System > Preferences > Advanced Desktop Effects Settings. Scroll down to Effects and enabled Blur Windows. Then click the Blur Windows button to open the configuration panel. Set "Alpha blur windows" to <strong>(class=Gnome-terminal)</strong>, Check <strong>Alpha Blur</strong>, set "Blur Filter" to <strong>Gaussian</strong>, and set "Gaussian Radius" to <strong>9</strong>.</p>
<p><a href='http://www.toosweettobesour.com/wp-content/uploads/2008/05/screenshot-compizconfig-settings-manager.png'><img src="http://www.toosweettobesour.com/wp-content/uploads/2008/05/screenshot-compizconfig-settings-manager-300x251.png" alt="Settings for Alpha-Blurred gnome-terminal" title="Screenshot of CompizConfig Settings" width="300" height="251" class="aligncenter size-medium wp-image-51" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2008/05/15/compizfusion-blur-your-terminal-window/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.235 seconds -->
<!-- Cached page served by WP-Cache -->
