<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Planet Kodiak</title>
	<atom:link href="http://www.planetkodiak.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.planetkodiak.com</link>
	<description>Because there aren&#039;t enough opinions on the net...</description>
	<lastBuildDate>Fri, 27 Aug 2010 06:50:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Show A Twitter Status Update On A Page Using Javascript</title>
		<link>http://www.planetkodiak.com/code/show-a-twitter-status-update-on-a-page-using-javascript/</link>
		<comments>http://www.planetkodiak.com/code/show-a-twitter-status-update-on-a-page-using-javascript/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 07:09:13 +0000</pubDate>
		<dc:creator>Cory Fischer</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.planetkodiak.com/?p=88</guid>
		<description><![CDATA[So you want to show your Twitter status on your website? Don't want to deal with server-side scripts? Luckily, Twitter gives you an excellent API to call that makes this pretty easy.]]></description>
			<content:encoded><![CDATA[<p>So you want to show your Twitter status on your website? Don&#8217;t want to deal with server-side scripts? Luckily, Twitter gives you an excellent API to call that makes this pretty easy.</p>
<p>Because we live in crazy times, lets start at the end. The Twitter call will be made after all your code. It returns a JSON object to your code. Don&#8217;t worry if you don&#8217;t know JSON, it&#8217;s a pretty simple object and no real world knowledge of JSON is necessary to get your code up and running. The API is as follows (note: <strong>change the &#8220;planetkodiak&#8221; URL to your own user ID</strong>).</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;http://twitter.com/statuses/user_timeline/planetkodiak.json?callback=twitterCallback2&amp;count=1&quot;&gt;&lt;/script&gt;</pre></div></div>

<p>The important parts here are the user name and the count. The username above is planetkodiak.json. If your twitter username is &#8220;bob&#8221; then use bob.json. The count is important in that it will return your most recent posts. In this example we&#8217;re only returning the most recent.</p>
<p>Remember, <strong>this should come after the rest of your code</strong> as it&#8217;s expecting a certain function.</p>
<p>Now that we&#8217;ve started at the end, lets continue to the beginning (then we&#8217;ll finish in the middle because I can&#8217;t make it TOO easy for you). In the &lt;head&gt; you can add a javascript with inline code or an external file; your choice. For the example below I&#8217;ll give you the code for the inline script.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> twitterCallback2<span style="color: #009900;">&#40;</span>twitters<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> statusHTML <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>twitters.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> username <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">user</span>.<span style="color: #660066;">screen_name</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">status</span> <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">text</span>.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/((https?|s?ftp|ssh)\:\/\/[^&quot;\s\&lt;\&gt;]*[^.,;'&quot;&gt;\:\s\&lt;\&gt;\)\]\!])/g</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'&lt;a href=&quot;'</span><span style="color: #339933;">+</span>url<span style="color: #339933;">+</span><span style="color: #3366CC;">'&quot;&gt;'</span><span style="color: #339933;">+</span>url<span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/a&gt;'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\B@([_a-z0-9]+)/ig</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>reply<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">return</span>  reply.<span style="color: #660066;">charAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;a href=&quot;http://twitter.com/'</span><span style="color: #339933;">+</span>reply.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&quot;&gt;'</span><span style="color: #339933;">+</span>reply.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/a&gt;'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		statusHTML.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;span class=&quot;status&quot;&gt;'</span><span style="color: #339933;">+</span><span style="color: #000066;">status</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/span&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'twitterStatus'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> statusHTML.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The name of this function is important, as the JSON is expecting it. It is also ready for multiple statuses if you choose to change the amount of twitter statuses from one to many.</p>
<p>The idea of this function is to build up a variable with the Twitter content and replace the inner HTML of an element with the ID of &#8220;twitterStatus&#8221; with the contents of that variable. If you&#8217;ll notice the only thing we&#8217;re putting in the HTML is this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">statusHTML.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;span class=&quot;status&quot;&gt;'</span><span style="color: #339933;">+</span><span style="color: #000066;">status</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/span&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The only variable we&#8217;re using is the status itself. The status is set a few lines above with this code:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">status</span> <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">text</span><span style="color: #339933;">;</span></pre></div></div>

<p>It also includes some replacement text for URL&#8217;s. The &#8220;twitters&#8221; variable is the JSON variable that is sent to this function. It is a multi-dimensional array with a number of key values; &#8220;text&#8221; is the one with the value of the Twitter status itself, therefore the code is: twitters[i].text.</p>
<p>If you wanted to include your Twitter ID, you would do:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> id <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">id</span><span style="color: #339933;">;</span></pre></div></div>

<p>If you wanted to include your Twitter username, you would do:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> username <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">user</span>.<span style="color: #660066;">screen_name</span><span style="color: #339933;">;</span></pre></div></div>

<p>Here is a full list of key/value pairs you can use from one of my recent Twitter updates:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">	<span style="color: #009900;">&#123;</span>
	<span style="color: #3366CC;">&quot;in_reply_to_status_id&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;contributors&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;geo&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;retweet_count&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;truncated&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;created_at&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Fri Aug 13 07:29:29 +0000 2010&quot;</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;coordinates&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;source&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;web&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;place&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;retweeted&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;favorited&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;user&quot;</span><span style="color: #339933;">:</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #3366CC;">&quot;contributors_enabled&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;description&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Cory Fischer - Software developer at PlanetKodiak.com&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;lang&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;en&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;geo_enabled&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_use_background_image&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;time_zone&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Alaska&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;created_at&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Sat Jan 16 02:33:15 +0000 2010&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;location&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Washington State&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;notifications&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_background_color&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;9ae4e8&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;verified&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_background_image_url&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://s.twimg.com/a/1281662294/images/themes/theme1/bg.png&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;follow_request_sent&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;following&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_text_color&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;000000&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_background_tile&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_link_color&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;0000ff&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;followers_count&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">5</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;protected&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_image_url&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://a0.twimg.com/profile_images/864422532/logo_300x300_normal.png&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;listed_count&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;friends_count&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">7</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_sidebar_fill_color&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;e0ff92&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Planet Kodiak&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;statuses_count&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">11</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;screen_name&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;planetkodiak&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">105344133</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;show_all_inline_media&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;utc_offset&quot;</span><span style="color: #339933;">:-</span><span style="color: #CC0000;">32400</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;favourites_count&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;profile_sidebar_border_color&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;87bc44&quot;</span><span style="color: #339933;">,</span>
			<span style="color: #3366CC;">&quot;url&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;http://www.planetkodiak.com&quot;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;in_reply_to_user_id&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span><span style="color: #CC0000;">21045178144</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;in_reply_to_screen_name&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;text&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Ironically, the W3 (the site that heads up the web accessibility initiative) has a web accessibility issue http://bit.ly/cK7Ail&quot;</span>
	<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now, once you&#8217;ve got your javascript function configured the way you want, you need to create an HTML element with the ID of &#8220;twitterStatus&#8221;. </p>
<p>The order of events is to have your twitterCallback2() function in your header, have your twitterStatus element in your body, then link to the Twitter API last. In it&#8217;s simplest form, your code should look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">&lt;html&gt;
&lt;head&gt;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
<span style="color: #003366; font-weight: bold;">function</span> twitterCallback2<span style="color: #009900;">&#40;</span>twitters<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> statusHTML <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>twitters.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> username <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">user</span>.<span style="color: #660066;">screen_name</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">status</span> <span style="color: #339933;">=</span> twitters<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">text</span>.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/((https?|s?ftp|ssh)\:\/\/[^&quot;\s\&lt;\&gt;]*[^.,;'&quot;&gt;\:\s\&lt;\&gt;\)\]\!])/g</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'&lt;a href=&quot;'</span><span style="color: #339933;">+</span>url<span style="color: #339933;">+</span><span style="color: #3366CC;">'&quot;&gt;'</span><span style="color: #339933;">+</span>url<span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/a&gt;'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\B@([_a-z0-9]+)/ig</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>reply<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">return</span>  reply.<span style="color: #660066;">charAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;a href=&quot;http://twitter.com/'</span><span style="color: #339933;">+</span>reply.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&quot;&gt;'</span><span style="color: #339933;">+</span>reply.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/a&gt;'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		statusHTML.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;span class=&quot;status&quot;&gt;'</span><span style="color: #339933;">+</span><span style="color: #000066;">status</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'&lt;/span&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'twitterStatus'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> statusHTML.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span>
&lt;title&gt;Twitter&lt;/title&gt;
&lt;/head&gt;
&nbsp;
&lt;body&gt;
&nbsp;
&lt;div id=&quot;twitterStatus&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://twitter.com/statuses/user_timeline/planetkodiak.json?callback=twitterCallback2&amp;count=1&quot;&gt;&lt;/script&gt;
&nbsp;
&lt;/body&gt;
&lt;/html&gt;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.planetkodiak.com/code/show-a-twitter-status-update-on-a-page-using-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Practices Developers Should Avoid</title>
		<link>http://www.planetkodiak.com/opinion/practices-developers-should-avoid/</link>
		<comments>http://www.planetkodiak.com/opinion/practices-developers-should-avoid/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 06:04:57 +0000</pubDate>
		<dc:creator>Cory Fischer</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[SEO]]></category>

		<guid isPermaLink="false">http://www.planetkodiak.com/?p=79</guid>
		<description><![CDATA[Every developer wants to create the best site for their users. Though often times they will add functionality, use formats, or design in a way that matches what they perceive to be a "standard". Unfortunately, just because something is used often doesn't mean it's a good thing. In this article I'll discuss some common practices that you may have done without even considering other options.]]></description>
			<content:encoded><![CDATA[<p>Every developer wants to create the best site for their users. Though often times they will add functionality, use formats, or design in a way that matches what they perceive to be a &#8220;standard&#8221;. Unfortunately, just because something is used often doesn&#8217;t mean it&#8217;s a good thing. In this article I&#8217;ll discuss some common practices that you may have done without even considering other options.</p>
<h3>Complicated comments</h3>
<p>We often times think that our site is the center of the internet universe, but unless you&#8217;re Facebook or Google you may want to rethink how your users interact with your site. Unless you&#8217;re using a common interface such as <a href="http://disqus.com/comments/" target="_blank">DISQUS</a> for your comments, you should leave your site&#8217;s comments open and not force them to register for an account. It&#8217;s unlikely someone will want to go through the registration process (especially if they have to wait for a confirmation email) since people don&#8217;t generally like to have dozens or even hundreds of accounts littered across the internet.</p>
<p>There are exceptions to the rule, and certainly large corporate websites are a part of that exception (e.g. Facebook &#038; Google), however unless you specifically want to cause your users to go through an arduous process, you should let them comment freely or use a cross-site commenting system such as DISQUS.</p>
<h3>SEO over usability</h3>
<p><a href="http://en.wikipedia.org/wiki/Search_engine_optimization" target="_blank">SEO</a> is an important aspect of any site&#8217;s push to get more visitors. The problem comes when you program to SEO so much that it causes problems with your users ability to complete their intended tasks. If you&#8217;re modifying your navigation or presentation layer to accommodate SEO, you&#8217;re doing it wrong.</p>
<p>Truth-be-told about SEO: content is king! You want good search results you need to worry about two things.<br />
1) Get links from other, important sites. If Google (or Yahoo, Bing, and others for that matter) see that you&#8217;re getting links to your site from other important sites, your search rankings will skyrocket to the top. That&#8217;s 90% of the battle.<br />
2) Write good content. You want your site to be found with the proper search terms. To do this, write good content. Between this and getting important links, that&#8217;s 99% of the battle. Everything else, including proper &lt;h1&gt; tags and presentation layer changes, is just fluff. They can help, but only marginally and usually at the expense of your users. The same ones you were so desperate to get to your site through a search engine I might add.</p>
<p>As far as presentation layer is concerned, you may be asking yourself, &#8220;does Flash really inhibit my SEO attempts?&#8221;. The answer is&#8230; maybe! If you&#8217;re not using Flash properly, you can. Google has a harder time reading flash files, and only wants to index text. if you don&#8217;t have a mechanism to accommodate search engines suddenly content, which is king, becomes second fiddle. There are many ways to fix this, but the best and easiest way is to hide your content in a &lt;div&gt; tag that has javascript replace the contents with your flash file. This is often confused as <a href="http://en.wikipedia.org/wiki/Cloaking" target="_blank">Cloaking</a>. Cloaking refers to when you give the search engine <em>different</em> content then what you present to your users. If the content is the same, you&#8217;re golden. However, if you present &#8220;<strong>Storing MySQL Data in Hierarchical format</strong>&#8221; to your users, and give Google search terms like &#8220;<strong>Brittany Spears, Lebron James, and Lindsey Lohan</strong>&#8221; that&#8217;s when you get blacklisted.</p>
<p>Remember to use rich media responsibly, that content is king, and usability trumps SEO.</p>
<h3>Video Player Controls</h3>
<p>This is a simple one that many people often do because other people do it. Just because everyone does it doesn&#8217;t make it a standard. Well, maybe that&#8217;s not true, but if Apple jumps off a bridge and all that. </p>
<p>It is quite common to see video players with audio controls. This is absolutely unnecessary as all computers have audio controls. Many have dedicated buttons, while Windows has it right in the bottom corner. Most users already have their audio at a level they already want, so why reinvent the wheel? If you must include an audio control in your video player, please remember to default it to max volume. This is something that, for example, <a href="http://cnet.com" target="_blank">CNET</a> does poorly. Because most users have their audio at a level they already want, having your video player at something less than max means they must either 1) adjust it on the video player for each video they watch, or 2) adjust their system audio to start watching, then adjust their system audio back after watching it.</p>
<h3>Targeting New Windows</h3>
<p>This is a simple one but an important one. It is generally a good idea to target links to other websites to a new window, and links within your own domain to the same window. This makes sure that users are still connected to your site. The exception to the rule that says &#8220;target links within your own domain to the same window&#8221; is when you&#8217;re in a large article (much like this) and you have links in the middle. This disrupts the flow of your article. Target references in a new window so users can come back to your article, or save the links for when they are finished.</p>
<h3>Fancy Dates</h3>
<p>Fancy dates often look like this: &#8220;About an Hour ago&#8221; or &#8220;14 hours ago&#8221;. Instead of generalizing your time, let your users know the exact date and time something happened. Users are likely more interested in knowing what time something happened than knowing how long ago it was. It is less specific to use fancy dates, because your users don&#8217;t know if &#8220;2 hours ago&#8221; really means &#8220;1 1/2 hours ago and I rounded up&#8221; or &#8220;2 hours and 59 minutes ago and I don&#8217;t count minutes&#8221;. Give your users the full story!</p>
<h3>Multi-page Articles</h3>
<p>Click here to read page 2. Ok, not really, but this is often the case on many sites. Is it really that hard to put a large article on one page? It is much easier to scroll than to traverse through a half dozen pages. Even if your page has a lot of rich media content, ask yourself if it&#8217;s really necessary to use multi-page layouts first.</p>
<h3>Overuse of Ajax</h3>
<p><a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29" target="_blank">Ajax</a> is an excellent tool to make your internet applications richer. I am personally a huge fan of Ajax, but if used improperly it can be a huge liability to users. Ask yourself one of these questions:</p>
<ul>
<li>Will my users want to access this content through a URL?</li>
<li>Will my users want to use the back/forward buttons in their browser?</li>
</ul>
<p>If the answer is yes to either of these, then reconsider using Ajax to present your content. There are obvious <a href="http://www.asual.com/swfaddress/" target="_blank">ways around this</a>, but they are generally clunky and not always worth the effort.</p>
<h3>Conclusion</h3>
<p>These are just a few examples of how not to do things. They all have a common theme: Users First! If you always remember to question each thing you do, even if it seems to be a standard, you&#8217;ve got at least one notch in your &#8220;I&#8217;m a good developer&#8221; belt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.planetkodiak.com/opinion/practices-developers-should-avoid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Truth About HTML5</title>
		<link>http://www.planetkodiak.com/opinion/the-truth-about-html5/</link>
		<comments>http://www.planetkodiak.com/opinion/the-truth-about-html5/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 08:50:38 +0000</pubDate>
		<dc:creator>Cory Fischer</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[HTML5]]></category>

		<guid isPermaLink="false">http://www.planetkodiak.com/?p=73</guid>
		<description><![CDATA[There's a new buzz word in the technology world, and its name is HTML5. Since the term "Web 2.0" is losing its luster and becoming a dated phrase, every one is going nuts over this new term. Is HTML5 just a marketing title like "Web 2.0" or is there really something worth investing in? Is HTML5 the future? Will HTML5 really kill Flash?]]></description>
			<content:encoded><![CDATA[<p>There are many misconceptions out on the web about what HTML5 actually is, so I want to address this first. Most misconceptions surrounding the discussion are that HTML5 is an Adobe Flash replacement or even just a video player. Although it supports embedded video without the need for plugins, HTML5 is not just about video in your browser. It is a specification that will eventually be a recommendation from the W3C (World Wide Web Consortium) to browser makers on how HTML code should be rendered. Normally, recommendations such as HTML 4.01, the most commonly used specification today, stops there. However, HTML5 also has specifications on how to make GPU and other OS-level elements available to the HTML5 API so that web developers can program their sites once and end up getting the same visual results in any browser on any platform from the same code. At least that&#8217;s what&#8217;s supposed to happen. Once the W3C released a recommendation, it is considered a &#8220;standard&#8221;.</p>
<p>Everyone is pushing for HTML5 now as if it&#8217;s already been recommended by the W3C. The iPhone and iPad are already supposedly supporting it. The problem is, this specification is still in draft. Browser makers like Mozilla, Google, and Apple are all trying to add the functionality to their browsers to &#8220;beat each other&#8221; to punch by supporting things before they are a standard. This makes for a bad recipe when a recommendation changes before it becomes a standard. Currently, many browser makers are doing the same thing with CSS3. Since things such as rounded corners are only supported in the CSS3 specification, browser makers add their rendering engine&#8217;s prefix before the current specs code so that if the recommendation changes, they&#8217;re still only screwing up their &#8220;proprietary&#8221; version of the code. For example, if you wanted the top left corner of a div element to be rounded, the specification currently reads that your code should look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">div <span style="color: #00AA00;">&#123;</span>
	border-top-left-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>That&#8217;s one line of code that should render identically in every browser. Unfortunately it doesn&#8217;t render in any browser since CSS3 is still in draft and not a standard. So to get this working in modern browsers, Mozilla, Google, and Apple have added their own versions:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">div <span style="color: #00AA00;">&#123;</span>
	-moz-border-radius-topleft<span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span>
	-webkit-border-top-left-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Both have the browser-specific prefix (-moz for Gecko engines like Firefox, -webkit for webkit browsers like Chrome and Safari), but are also different in name. Instead of ending with one word &#8220;topleft&#8221; webkit uses &#8220;top-left&#8221; before the word &#8220;radius&#8221;. The reason is because the Gecko engine supported the border radius property before anyone else, and then the recommendation changed the format for the border-radius property. Now we have two ways to make rounded corners for two different browser engines that don&#8217;t match and neither one of them is true CSS3.</p>
<p>HTML5 is in the same situation as CSS3. That is, it&#8217;s a mess. Not HTML5 per-se, but browser implementation of it. The video streaming, for example, was first supported by Firefox using the Ogg Theora codec. This was the spec in the HTML5 recommendation until Apple decided to raise a stink about it and said they would only support the H.264 codec. Apple shipped Safari 4 with quasi-support for the HTML5 video element and the H.264 element. Google said they would ship Chrome to support both codecs, while Microsoft said they will only support H.264 once IE9 comes out. Because all these browser makers started throwing their weight around and refusing to support something before it became a standard, the specification to require a specific codec was dropped.</p>
<p>I personally believe there should be one codec for all browsers to support. That is the whole idea of an &#8220;open standard&#8221; after all. Another aspect of an open standard is… umm… openness. The Ogg Theora codec is completely open source, meaning anyone can use it for any reason in any product without paying royalties. H.264 is currently maintained by ISO Moving Picture Experts Group (MPEG) and anyone who wants to license H.264 has to pay a hefty price. Two of its patent holders: Microsoft and Apple. So if Mozilla, Google or anyone else wants to build a browser that supports HTML5, they would have to pay Microsoft and Apple (among others) to use it. Now, there are some benefits to H.264. It delivers DVD quality video at twice the bit-rate with low processor usage that could benefit mobile devices. These benefits do not out weigh the implications of an open standard in my opinion. If any browser maker has to pay a few corporations, that essentially means that a few companies will &#8220;own&#8221; the internet. </p>
<p>This does not necessarily mean that Ogg Theora is the right choice, but I believe it is best for the web at this point. Is the argument about mobile devices supporting this codec valid? Well, that brings up another issue with HTML5. The specification is not due to become a W3C recommendation until 2022. By then, mobile devices will be more powerful than todays laptops. </p>
<p>There are so many things that can change between now and 2022, and the browser makers will come up with their own proprietary &#8220;standards&#8221; in the years to come. Meanwhile, web developers will still have to code for multiple browsers and not be able to take advantage of the open standards that HTML5 is supposed to represent.</p>
<p>So, will HTML5&#8242;s video element (as well as the canvas element) kill Flash? It&#8217;s hard to say at this point, but since there are currently many limitations to the HTML 5 draft, such as full-screen mode, no interactive elements, etc. I don&#8217;t foresee this happening any time in the near future. Also, Flash is currently installed on 98% of computers world wide, while Internet Explorer has 65% of the browser usage share and doesn&#8217;t have a version that supports any HTML5 in one form or another. Until developers can program to 90% of the web, they will generally stick with what&#8217;s supported. So once IE9 comes out, which will supposedly support the video element, it will slowly have to gain usage share while older versions such as IE6, IE7, and IE8 fizzle out of usage. If you think that&#8217;s going to happen quickly, you&#8217;ll be interested in knowing that IE6, which was released in 2001, still currently holds around 17% of the market. Until this happens, developers would have to use something such as Flash as a fall back for older browsers, and since Flash currently does a better job than HTML5, developers will likely stick with Flash for a very long time instead of programming two versions of the same video.</p>
<p>My hope is that HTML5 will pick up steam and allow us developers to take advantage of features that are traditionally only seen in desktop applications. The web is fast moving, and HTML5 will have to become a recommendation well before 2022 if it is to succeed. If there is not a recommended codec for the video element, it would be better to allow multiple codecs so that open ones can exist. The web should remain open and stay away from any sort of proprietary ownership.</p>
<p>Is HTML5 the future? Yes, I believe it is. Lets just hope it&#8217;s not the far future.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.planetkodiak.com/opinion/the-truth-about-html5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hierarchical Data in MySQL</title>
		<link>http://www.planetkodiak.com/code/hierarchical-data-in-mysql/</link>
		<comments>http://www.planetkodiak.com/code/hierarchical-data-in-mysql/#comments</comments>
		<pubDate>Fri, 07 May 2010 07:03:03 +0000</pubDate>
		<dc:creator>Cory Fischer</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.planetkodiak.com/?p=45</guid>
		<description><![CDATA[Managing a site structure, or any other structure, in a database often gets overlooked. It's pretty simple and a common standard to use what's called the Adjacency List Model without sitting down and thinking about other possible solutions. In this post I'll talk about a different method of storing hierarchical data in a relational database.]]></description>
			<content:encoded><![CDATA[<p>For the purposes of this post, we&#8217;ll use a fake website and use the hierarchy in the image below.</p>
<p><img title="hierarchical_site" src="/wp-content/uploads/2010/05/hierarchical_site.gif" alt="" /></p>
<p>Managing a site structure, or any other structure, in a database often gets overlooked. It&#8217;s pretty simple and a common standard to use what&#8217;s called the Adjacency List Model without sitting down and thinking about other possible solutions. The Adjacency List Model in a database table consists of an ID and a Parent ID. The Parent ID usually refers to the ID of another record in the same table. Here is an example of what one might look like:</p>
<pre>------------------------------------------------
|  ID  |      page_name          |  parent_id  |
------------------------------------------------
|  1   |       Home              |  NULL       |
|  2   |       Books             |  1          |
|  3   |       Best Sellers      |  2          |
|  4   |       Cloths            |  1          |
|  5   |       Toys              |  1          |
|  6   |       Electronics       |  1          |
|  7   |       iPods             |  6          |
|  8   |       Computers         |  6          |
|  9   |       Desktops          |  8          |
|  10  |       Laptops           |  8          |
|  11  |       Netbooks          |  8          |
------------------------------------------------
</pre>
<p>Notice the Home page has an ID of 1 and no parent_id. Best Sellers has the parent_id of 2 which corresponds to the ID of 2 which belongs to Books. Desktops, Laptops and Netbooks all have a parent_id of 8 which corresponds to the ID of Computers, and Computers has 6 as the parent_id which corresponds to Electronics, and finally Electronics has 1 as its parent_id which corresponds to Home. This is the most common form of hierarchical data storage in a database. First thing you&#8217;ll notice is that it&#8217;s pretty simple. If I&#8217;m on a page and I need to find it&#8217;s parent, the SQL is easy.</p>
<p>Assume $page_id is the variable that corresponds to ID in the database. Lets retrieve its parent.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> pages
<span style="color: #993333; font-weight: bold;">WHERE</span> page_id <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span>
	<span style="color: #993333; font-weight: bold;">SELECT</span> parent_id <span style="color: #993333; font-weight: bold;">FROM</span> pages <span style="color: #993333; font-weight: bold;">WHERE</span> page_id <span style="color: #66cc66;">=</span> $page_id
<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Similarly, we could get all the child pages</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> pages <span style="color: #993333; font-weight: bold;">WHERE</span> parent_id <span style="color: #66cc66;">=</span> $page_id</pre></div></div>

<p>Now  you might be thinking there&#8217;s nothing wrong with this. After all, it&#8217;s very simple and easy to understand, but what if you want to find the entire hierarchy? Suppose you&#8217;re on &#8220;Laptops&#8221; and you want to get the crumbtrail all the way up to the Home page. (For simplicity and clarity, I&#8217;ll use the page &#8220;name&#8221; rather than the ID&#8217;s in my examples).</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> pageLevel1<span style="color: #66cc66;">.</span>page_name <span style="color: #993333; font-weight: bold;">AS</span> lev1<span style="color: #66cc66;">,</span> pageLevel2<span style="color: #66cc66;">.</span>page_name <span style="color: #993333; font-weight: bold;">AS</span> lev2<span style="color: #66cc66;">,</span>
	pageLevel3<span style="color: #66cc66;">.</span>page_name <span style="color: #993333; font-weight: bold;">AS</span> lev3<span style="color: #66cc66;">,</span> pageLevel4<span style="color: #66cc66;">.</span>page_name <span style="color: #993333; font-weight: bold;">AS</span> lev4
<span style="color: #993333; font-weight: bold;">FROM</span> pages <span style="color: #993333; font-weight: bold;">AS</span> pageLevel1
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> pages <span style="color: #993333; font-weight: bold;">AS</span> pageLevel2 <span style="color: #993333; font-weight: bold;">ON</span> pageLevel2<span style="color: #66cc66;">.</span>parent <span style="color: #66cc66;">=</span> pageLevel1<span style="color: #66cc66;">.</span>page_id
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> pages <span style="color: #993333; font-weight: bold;">AS</span> pageLevel3 <span style="color: #993333; font-weight: bold;">ON</span> pageLevel3<span style="color: #66cc66;">.</span>parent <span style="color: #66cc66;">=</span> pageLevel2<span style="color: #66cc66;">.</span>page_id
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> pages <span style="color: #993333; font-weight: bold;">AS</span> pageLevel4 <span style="color: #993333; font-weight: bold;">ON</span> pageLevel4<span style="color: #66cc66;">.</span>parent <span style="color: #66cc66;">=</span> pageLevel3<span style="color: #66cc66;">.</span>page_id
<span style="color: #993333; font-weight: bold;">WHERE</span> pageLevel1<span style="color: #66cc66;">.</span>page_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Home'</span>;</pre></div></div>

<p>The result is:</p>
<pre>---------------------------------------------------------------------
|   lev1         |   lev2         |   lev3         |   lev4         |
---------------------------------------------------------------------
|   Home         |   Electronics  |   Computers    |   Laptops      |
---------------------------------------------------------------------
</pre>
<p>There&#8217;s a problem with this. Besides the large amount of joins, this assumes we know the depths of the hierarchy. In a website application we generate the crumbtrail, navigations, and hierarchy trees dynamically. This Adjacency List Model is too flat and has no easy way of getting the depth of a node.</p>
<p>The Adjacency List Model is great for finding parents of nodes, but not so great at finding grand parent nodes, great grand parent nodes, even second-cousin-once-removed nodes, or the uncle-no-one-talks-about nodes.</p>
<p>Luckily, there is another solution to our database hierarchical structures. It&#8217;s called the Nested Set Model. This model uses two fields to determine the spot in the hierarchy as oppose to a single parent_id: a <em>left</em> and a <em>right</em>. Our example above would look like this in a database using the Nested Set Model:</p>
<pre>----------------------------------------------------
|  ID  |      page_name          |  lft  |	rgt	|
----------------------------------------------------
|  1   |       Home              |  1    |	22	|
|  2   |       Books             |  2    |	5	|
|  3   |       Best Sellers      |  3    |	4	|
|  4   |       Cloths            |  6    |	7	|
|  5   |       Toys              |  8    |	9	|
|  6   |       Electronics       |  10   |	21	|
|  7   |       iPods             |  11   |	12	|
|  7   |       Computers         |  13   |	20	|
|  9   |       Desktops          |  14   |	15	|
|  10  |       Laptops           |  16   |	17	|
|  11  |       Netbooks          |  18   |	19	|
----------------------------------------------------
</pre>
<p>If you&#8217;re unfamiliar with the Nested Set Model, this might be confusing. All you have to remember is that if an item&#8217;s &#8220;lft&#8221; and &#8220;rgt&#8221; fall between another rows lft and rgt, it is a sub-node of that row. (Notice this is not &#8220;left&#8221; and &#8220;right&#8221; as they are reserved words in SQL, so I used lft and rgt).</p>
<p>Here is a diagram of the the same site with the numbers added to give you an idea of the structure.</p>
<p><img class="alignnone size-medium wp-image-49" title="hierarchical_site_w-numbers" src="/wp-content/uploads/2010/05/hierarchical_site_w-numbers.gif" alt="" /></p>
<p>Since Home is the top of the hierarchy, it starts it&#8217;s lft with the lowest number, and rgt with the highest number; therefore any page that has an lft that&#8217;s GREATER than 1 and an rgt that&#8217;s LESS than 22 is a sub node of Home. Likewise, Books has 2 and 5 with Best Sellers having 3 and 4 making it a sub node of Books. We can then know that Best Sellers is also a sub node of Home because 3 and 4 fall between 1 and 22. Hopefully this is making some sense. If you need help following the flow of the above chart, follow the blue line of this chart. Notice the blue lines go in numeric order.</p>
<p><img class="alignnone size-full wp-image-48" title="hierarchical_site_follow" src="/wp-content/uploads/2010/05/hierarchical_site_follow.gif" alt="" width="700" height="352" /></p>
<p>This might seem quite a bit tougher than the Adjacency List Model, and you&#8217;d be right. The implementation is tougher, but once you start using it in your application you won&#8217;t be sorry. Let&#8217;s try to get a crumbtrail from &#8220;Laptops&#8221; again.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> parent<span style="color: #66cc66;">.</span>page_name
<span style="color: #993333; font-weight: bold;">FROM</span> pages <span style="color: #993333; font-weight: bold;">AS</span> node<span style="color: #66cc66;">,</span>
pages <span style="color: #993333; font-weight: bold;">AS</span> parent
<span style="color: #993333; font-weight: bold;">WHERE</span> node<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">BETWEEN</span> parent<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">AND</span> parent<span style="color: #66cc66;">.</span>rgt
<span style="color: #993333; font-weight: bold;">AND</span> node<span style="color: #66cc66;">.</span>page_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Laptops'</span>
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> parent<span style="color: #66cc66;">.</span>lft;</pre></div></div>

<p>This creates the same results:</p>
<pre>------------------
|   name         |
------------------
|   Home         |
|   Electronics  |
|   Computers    |
|   Laptops      |
------------------
</pre>
<p>This was much simpler. I just found &#8220;Laptops&#8221; lft and rgt and I&#8217;m basically saying &#8220;find me all the pages where the left is less than Laptop&#8217;s left and the right is greater than Laptop&#8217;s right&#8221;. This just works its way right up the hierarchy.</p>
<p>What about finding the entire depth of a tree with this model?</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> lft<span style="color: #66cc66;">,</span>rgt<span style="color: #66cc66;">,</span>page_id<span style="color: #66cc66;">,</span>page_name<span style="color: #66cc66;">,</span>
    <span style="color: #66cc66;">&#40;</span>
		<span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span>page_id<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> pages
		<span style="color: #993333; font-weight: bold;">WHERE</span> lft <span style="color: #66cc66;">&lt;</span> node<span style="color: #66cc66;">.</span>lft 
		<span style="color: #993333; font-weight: bold;">AND</span> rgt <span style="color: #66cc66;">&gt;</span> node<span style="color: #66cc66;">.</span>rgt
		<span style="color: #993333; font-weight: bold;">AND</span> node<span style="color: #66cc66;">.</span>lft <span style="color: #66cc66;">&lt;&gt;</span> <span style="color: #cc66cc;">0</span>
	<span style="color: #66cc66;">&#41;</span>
	<span style="color: #993333; font-weight: bold;">AS</span> depth
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`pages`</span> <span style="color: #993333; font-weight: bold;">AS</span> node
<span style="color: #993333; font-weight: bold;">WHERE</span> lft <span style="color: #66cc66;">&lt;&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> lft</pre></div></div>

<p>The subquery (line 2 above) is an easy way to find how deep inside the hierarchy we are. We can use this in our code to create a full tree:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000088;">$last_depth</span>	<span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$output</span>		<span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$i</span>		<span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pageList</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT lft,rgt,page_id,page_name,
	(
		SELECT COUNT(page_id) FROM pages 
		WHERE lft &lt; node.lft 
		AND rgt &gt; node.rgt 
		AND node.lft &lt;&gt; 0
	) AS depth 
	FROM `pages` AS node 
	WHERE lft &lt;&gt; 0 ORDER BY lft&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pageList</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">==</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$liOffset</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'depth'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">// first (and therefore highest) in the hierarchy</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$current_depth</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'depth'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$last_depth</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$current_depth</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #990000;">str_repeat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;/ul&gt;&lt;/li&gt;'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$last_depth</span><span style="color: #339933;">-</span><span style="color: #000088;">$current_depth</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;&lt;li id='page_&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;'&gt;&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'rgt'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">!=</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'lft'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;ul&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/li&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$last_depth</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$current_depth</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$i</span><span style="color: #339933;">++;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$last_depth</span> <span style="color: #339933;">&gt;=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$liOffset</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/ul&gt;&lt;/li&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$last_depth</span><span style="color: #339933;">--;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$output</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/ul&gt;'</span><span style="color: #339933;">;</span></pre></div></div>

<p>This will give you a perfect &lt;ul&gt; tree with just one, simple SQL statement. Hopefully, you&#8217;re starting to see the power of the Nested Set Model compared to the Adjacency List Model. The SQL can get more complicated, but it&#8217;s much easier on the MySQL engine. Here is an example of getting just the immediate sub nodes, for example, Books, Cloths, Toys, and Electronics from &#8220;Home&#8221; but not Best Sellers, iPods, Computers etc.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> node<span style="color: #66cc66;">.</span>page_name<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span>COUNT<span style="color: #66cc66;">&#40;</span>parent<span style="color: #66cc66;">.</span>page_name<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #66cc66;">&#40;</span>sub_tree<span style="color: #66cc66;">.</span>depth <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> depth
<span style="color: #993333; font-weight: bold;">FROM</span> pages <span style="color: #993333; font-weight: bold;">AS</span> node<span style="color: #66cc66;">,</span>
	pages <span style="color: #993333; font-weight: bold;">AS</span> parent<span style="color: #66cc66;">,</span>
	pages <span style="color: #993333; font-weight: bold;">AS</span> sub_parent<span style="color: #66cc66;">,</span>
	<span style="color: #66cc66;">&#40;</span>
		<span style="color: #993333; font-weight: bold;">SELECT</span> node<span style="color: #66cc66;">.</span>page_name<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span>COUNT<span style="color: #66cc66;">&#40;</span>parent<span style="color: #66cc66;">.</span>page_name<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> depth
		<span style="color: #993333; font-weight: bold;">FROM</span> pages <span style="color: #993333; font-weight: bold;">AS</span> node<span style="color: #66cc66;">,</span>
		pages <span style="color: #993333; font-weight: bold;">AS</span> parent
		<span style="color: #993333; font-weight: bold;">WHERE</span> node<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">BETWEEN</span> parent<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">AND</span> parent<span style="color: #66cc66;">.</span>rgt
		<span style="color: #993333; font-weight: bold;">AND</span> node<span style="color: #66cc66;">.</span>page_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Home'</span>
		<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> node<span style="color: #66cc66;">.</span>page_name
		<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> node<span style="color: #66cc66;">.</span>lft
	<span style="color: #66cc66;">&#41;</span><span style="color: #993333; font-weight: bold;">AS</span> sub_tree
<span style="color: #993333; font-weight: bold;">WHERE</span> node<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">BETWEEN</span> parent<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">AND</span> parent<span style="color: #66cc66;">.</span>rgt
	<span style="color: #993333; font-weight: bold;">AND</span> node<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">BETWEEN</span> sub_parent<span style="color: #66cc66;">.</span>lft <span style="color: #993333; font-weight: bold;">AND</span> sub_parent<span style="color: #66cc66;">.</span>rgt
	<span style="color: #993333; font-weight: bold;">AND</span> sub_parent<span style="color: #66cc66;">.</span>page_name <span style="color: #66cc66;">=</span> sub_tree<span style="color: #66cc66;">.</span>page_name
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> node<span style="color: #66cc66;">.</span>page_name
<span style="color: #993333; font-weight: bold;">HAVING</span> depth <span style="color: #66cc66;">&lt;=</span> <span style="color: #cc66cc;">1</span>
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> node<span style="color: #66cc66;">.</span>lft;</pre></div></div>

<p>The results are:</p>
<pre>----------------------------
|   name         |  Depth  |
----------------------------
|   Home         |  0      |
|   Books        |  1      |
|   Cloths       |  1      |
|   Toys         |  1      |
|   Electronics  |  1      |
----------------------------
</pre>
<p>If you familiarize yourself with this model, many things will become second nature to you. You may ask yourself, &#8220;how do I add a new node in the Nested Set Model?&#8221;. I will leave you not with the SQL, but with the theory. If you wanted to add a node &#8220;Servers&#8221; under &#8220;Computers&#8221; to the right of &#8220;Netbooks&#8221; you would just make the new &#8220;lft&#8221; be 20 and the &#8220;rgt&#8221; be 21, and every other node that has an lft or rgt greater than or equal to 20 should have 2 more added to it.</p>
<h3>The downside of the Nested Set Model</h3>
<p>Although I feel that in many cases the Nested Set Model is superior to the Adjacency List Model, there are some negatives.</p>
<p>1. It is not widely used, therefore support when you run into issues is a limited. You may find some help online, but the vast majority of users and existing applications are not using this model.</p>
<p>2. Data corruption is possible. If you make a mistake in your code when you add a new node, move a node, delete a node etc. you may cause data corruption. For example, what happens if you try to move a Node to be a child of one of it&#8217;s on children? If you create your script objects right and always use them after extensively testing to make sure they always work, you should be fine. However if someone goes straight into the database and changes some random pages &#8220;lft&#8221; value to zero, the repercussions could involve restoring your database to a previous backup or meticulously going through the hierarchy in the back end and manually updating the nodes yourself. This is not a fun task!</p>
<p>3. It can be hard to learn. It&#8217;s a steep learning curve. I had to read the same article probably ten times before I fully grasped the SQL queries, but eventually it all clicked, and now that I use it in my applications I feel confident in many of the custom requests I receive.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.planetkodiak.com/code/hierarchical-data-in-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rewriting URL&#8217;s with mod_rewrite</title>
		<link>http://www.planetkodiak.com/code/rewriting-urls-with-mod_rewrite/</link>
		<comments>http://www.planetkodiak.com/code/rewriting-urls-with-mod_rewrite/#comments</comments>
		<pubDate>Sat, 01 May 2010 09:27:12 +0000</pubDate>
		<dc:creator>Cory Fischer</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[regex]]></category>

		<guid isPermaLink="false">http://www.planetkodiak.com/?p=26</guid>
		<description><![CDATA[Rewriting URL's from difficult-to-read addresses to simple, clean addresses can make your website much more user-friendly and SEO-friendly, but it can be difficult to accomplish without the proper tools. Enter mod_rewrite! Mod_rewrite is a part of the Apache web server that acts as a proxy before content from the web server is returned to your browser...]]></description>
			<content:encoded><![CDATA[<p>Rewriting URL&#8217;s from difficult-to-read addresses to simple, clean addresses can make your website much more user-friendly and SEO-friendly, but it can be difficult to accomplish without the proper tools. Enter mod_rewrite! Mod_rewrite is a part of the Apache web server that acts as a proxy before content from the web server is returned to your browser. If your server isn&#8217;t running Apache then there are also extensions available for IIS such as the URL Rewriter.</p>
<p>What is the benefit of this? Well, how many times have you come across a link like this while browsing?</p>
<p>http://www.example.com/some-dir/index.php?page=animals&amp;animal=dogs&amp;action=videos</p>
<p>First thing is, this is not very descriptive and hard for users to remember. Second, this isn&#8217;t going to get you very good search results in Google or any other search engine. Search engines much prefer URL&#8217;s to look something like this:</p>
<p>http://www.example.com/animals/dogs/videos</p>
<h3>Coding in mod_rewrite</h3>
<p>So how does mod_rewrite work to turn the nasty looking first link into the super nice looking, SEO-friendly second link? It all starts with the .htaccess file (yes, it starts with a dot &#8220;.&#8221;). I&#8217;ve always been better at learning-by-doing or learning-by-seeing, so lets just jump into the code. First, I&#8217;ve created a file in the root of my site called .htaccess. In it are some simple lines of code like this:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_rewrite.c&gt;
    <span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
    <span style="color: #adadad; font-style: italic;"># send any non-files or non-folders to the root index.php file</span>
    <span style="color: #00007f;">RewriteCond</span> %{REQUEST_FILENAME} !-d
    <span style="color: #00007f;">RewriteCond</span> %{REQUEST_FILENAME} !-f
    <span style="color: #00007f;">RewriteRule</span> ^(.*)$ /index.php?page=$<span style="color: #ff0000;">1</span> [QSA,L]
&lt;/<span style="color: #000000; font-weight:bold;">IfModule</span>&gt;</pre></div></div>

<p>This starts off with a conditional statement checking to see if Apache has the mod_rewrite module at all to avoid errors. Inside the &#8216;if&#8217; statement is the actual code. The first line &#8220;RewriteEngine On&#8221; simply says we&#8217;re activating mod_rewrite. This is a quick and easy way to turn URL rewriting on/off without having to delete or comment out a bunch of lines of code. The second line starts with a hash mark. This is how you do comments. The next two lines start with &#8220;RewriteCond&#8221;. These are conditions for the last line which is the actual rule. The condition lines aren&#8217;t even read unless the RewriteRule is met. The RewriteRule is read like this: &#8220;if the path of the URL matches my regular expression, then check the RewriteCond&#8221;. The &#8220;path&#8221; here is the part of the URL between the domain and the query string: http://www.example.com<span style="color: #ff0000;">/some/directory/file.php</span>?querystring. If you are unfamiliar with Regular Expressions, you can familiarize yourself with them with Regex cheat sheets online. I got the following from <a href="http://www.addedbytes.com" target="_blank">addbytes.com</a>.</p>
<p><a href="/wp-content/uploads/2010/04/regex.png" target="_blank"><img class="alignnone size-medium wp-image-24" title="regex" src="/wp-content/uploads/2010/04/regex-234x300.png" alt="" width="234" height="300" /></a></p>
<p>With the above regular expression: <span style="color: #ff0000;">^(.*)$</span> says &#8220;match 0 or more characters&#8221;, which any URL would match, so in this case the RewriteRule will always be met, and will always look at the RewriteCond. Since there is no other RewriteRule between the two RewriteCond they both apply to this rule. The first condition is making sure the file name (through <span style="color: #ff0000;">%{REQUEST_FILENAME}</span> ) is not a directory (the exclamation mark meaning *not* and the -d meaning directory). If it meets this condition, the second condition is ignored and we go back to the RewriteRule. The second RewriteCond is similar to the first except that &#8220;-f&#8221; makes sure this is not an existing file. The reason for this is that we don&#8217;t want to redirect every file on the server. If there currently exists a directory or file &#8220;/animals/dogs/videos&#8221; on the server then we don&#8217;t want to write over it, because remember our rewrite rule already said &#8220;any path&#8221; which would include the file we&#8217;re going to end up redirecting to. This would lead to an infinite loop of redirects, and nothing would be accessible.</p>
<p>Once one of these conditions is met, the rewrite engine goes back to the RewriteRule and looks at the URL that comes after the first regular expression. The regular expression and the URL are separated by a white space. So, our new URL that we want to go to is <span style="color: #ff0000;">/index.php?page=$1</span>. This would be a PHP file that exists in the root of the site. The PHP page has a parameter call &#8220;page&#8221; with the $1. This dollar sign and number means that anything that is within the first set of parenthesis in the first part of our RewriteRule should be put in this spot. In this case, the entire path. So in our example above, when someone tries to go to example.com/animals/dogs/videos, they will get redirected to example.com/index.php?page=/animals/dogs/videos. Now, you won&#8217;t see any of this in the browser, but that&#8217;s what your web server sees in the background. So in your index.php file you can do something like:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;page&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;page&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// display code based on this variable</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The above is obviously very simplified, but you get the idea. The last part of the RewriteRule is this: [QSA,L]. This is where you can specify extra information about he URL you are redirecting to. The QSA means that any additional query string parameters should be added to the new URL, and L means that this is the last rule that should be met; any other rules after this are ignored.</p>
<p>Click here for a <a href="/wp-content/uploads/2010/04/mod_rewrite-cheat-sheet-v2.pdf" target="_self">mod_rewrite cheat sheet</a>, thanks to <a href="http://www.addedbytes.com/" target="_blank">addbytes.com</a> for the list.</p>
<p><a href="/wp-content/uploads/2010/04/mod_rewrite-cheat-sheet-v2.pdf"><img class="alignnone size-medium wp-image-24" title="regex" src="/wp-content/uploads/2010/04/mod_rewrite-cheat-sheet.png" alt="" width="228" height="300" /></a></p>
<p>What about other, more complex redirects? Suppose we want to redirect old URLs to a new domain or website? Lets look at RewriteMaps.</p>
<p>RewriteMaps are variables that include an external text file to map certain keys to certain values. It might look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_rewrite.c&gt;
    <span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
    <span style="color: #00007f;">RewriteMap</span> sections_var txt:/usr/local/apache/conf/sections.txt
    <span style="color: #00007f;">RewriteCond</span> ﻿﻿﻿﻿%{QUERY_STRING}% section=([<span style="color: #ff0000;">0</span>-<span style="color: #ff0000;">9</span>]+)&amp;amp;item=(\w+)
    <span style="color: #00007f;">RewriteRule</span> ^/store/(.*) http://www.<span style="color: #00007f;">example</span>.com/store/${sections_var:%1|no-section}/%2/ [QSA,R=<span style="color: #ff0000;">301</span>,L]
&lt;/<span style="color: #000000; font-weight:bold;">ifModule</span>&gt;</pre></div></div>

<p>We also have a sections.txt file that looks like this:</p>
<pre><code>
1    Electronics
2    Music
3    MP3 Players
4    Televisions
5    Laptops
6    Netbooks
7    Desktops
8    Books
9    Software
10   Accessories
</code></pre>
<p>So for this example, we want our old, out of date URLs that people may have saved to their favorites, or Google may have indexed, to know where our new links are.</p>
<p>We reference this text file with the RewriteMap variable called sections_var. We then identify where the file is located by writing out the full path to the text file. In our RewriteRule we are checking to see if the incoming URL is a string starting with /store/ followed by zero or more characters. The RewriteCond checks to see if the query string has section=(one or more numbers) and also: &amp;item=(one or more words). An example of this kind of URL is: <span style="color: #ff0000;">site.com/store/index.php?section=10&amp;item=cases</span>.</p>
<p>Once we return to the RewriteRule, our first variable we come to is ${sections_var:%1|no-section}. Lets look at the first part: <span style="color: #ff0000;">${}</span> . This means a variable with code inside the braces. Inside the braces are two sets of information separated by the pipe character. If the part to the left of the pipe character isn&#8217;t found, the part to the right of the pipe character is read. The sections_var:%1 takes the first parenthesis value from the RewriteCond and finds the value in the sections.txt map. Look at the sections.txt map above, and if, for example, the number 7 is in the URL, the value &#8220;Desktops&#8221; is returned to the RewriteRule. Again, if no value is found the default &#8220;no-section&#8221; is given. The %2 is the second parenthesis given in the RewriteCond. Notice, a percentage is used here as opposed to the dollar sign like we used in the first example. When you &#8220;backreference&#8221; to the first part of the RewriteRule you use the dollar sign. When you backreference to the RewriteCond you use the percentage.</p>
<p>Last thing we have in this example is the R=301. This is telling the browser and all the little Google bots out there that this is a permanent redirect and it should update all the indexes it has.</p>
<h3>Tips</h3>
<p>If you want different sets of rules for different directories in your site, you can put the .htaccess files in lower directories as well. The farther down your directory it is the more it takes precedence. If you have an .htaccess file in /site/animals/ then any rules in that directory will run before any the rules of an .htaccess file in /site/ or the root directory.</p>
<p>Other issues you may have with rewriting URLs is that if you rewrite to a new domain, the URL will resolve to the new address. This may not be the desired effect. In this case, you would use the P flag in your brackets at the end of your RewriteRule:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_rewrite.c&gt;
    <span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
    <span style="color: #adadad; font-style: italic;"># any incoming URL on http://oldsite.com gets redirect to http://newsite.com</span>
    <span style="color: #00007f;">RewriteRule</span> ^(.*) http://www.newsite.com.com$<span style="color: #ff0000;">1</span> [QSA,P]
&lt;/<span style="color: #000000; font-weight:bold;">ifModule</span>&gt;</pre></div></div>

<p>This will take any incoming URL from oldsite.com and forward it to newsite.com, but you&#8217;ll still see &#8220;oldsite.com&#8221; in your browsers address bar. I have found this useful for things like redirecting my crossdomain.xml file when my application server is down and I have web services that need the crossdomain file.</p>
<h3>Optimizing Your Rewrite Code</h3>
<p>It is important to remember that every request made to your server comes through your mod_rewrite file. If you load a single page, it and all of its images, css files, javascripts and other files will go through this file separately. This could lead to slow load times if you have a lot of rules. Mod_rewrite is a powerful tool if you spend the time to optimize it properly. </p>
<p>Remember to utilize maps when possible. Maps won&#8217;t be queried if a rule&#8217;s conditions aren&#8217;t met. </p>
<p>Familiarize yourself with regular expressions to create fewer rules. Complex rules are harder to write but the rewrite engine can go through them quickly. Just remember, the fewer rules the better. When you need to write maps, they don&#8217;t get called as often as the rules, but try to keep them short anyway. A list of 10, 20 or 50 shouldn&#8217;t be too much for it, but if you create a map with 500 items you could see a big slow down.</p>
<p>Lastly, try to rely on your server-side code like the first example if possible. If you can send large chuncks of data to your PHP file and parse your the data with your PHP code (or whatever language you&#8217;re using) the PHP code can run a lot faster than your rewrite code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.planetkodiak.com/code/rewriting-urls-with-mod_rewrite/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
