<?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>Pixels from the Edge &#187; PHP</title>
	<atom:link href="http://pixelsfromtheedge.com/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://pixelsfromtheedge.com</link>
	<description>Creative // Technology // Digital // Interactive // Mobile // Advertising</description>
	<lastBuildDate>Fri, 02 Mar 2012 14:39:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Masters of the Universe &#8211; A Web Systems Suite</title>
		<link>http://pixelsfromtheedge.com/2009/10/masters-of-the-universe-a-web-systems-suite/</link>
		<comments>http://pixelsfromtheedge.com/2009/10/masters-of-the-universe-a-web-systems-suite/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 19:55:24 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Apps]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=38</guid>
		<description><![CDATA[Okay so this is really fun.  Just over four years ago I was working at a popular mortgage company as a back-end Tech Lead and was tasked with developing a PHP web framework to replace the dated and abominable system they currently had in place.  Their current &#8220;framework&#8221; was like the ugly bastard child of an <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC&#8230;</a> with grade three burns.  In other words it was total shit (all these years later and I still seem to harbor a great hate for it).  The web had been advancing quite nicely and we were now looking at the birth of Web]]></description>
			<content:encoded><![CDATA[<p><img style="padding:0px 0px 10px 10px;float:right;" title="He-Man-Movie-To-Start-Fresh-At-New-Studio" src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/He-Man-Movie-To-Start-Fresh-At-New-Studio.jpg" alt="He-Man-Movie-To-Start-Fresh-At-New-Studio" width="400" />Okay so this is really fun.  Just over four years ago I was working at a popular mortgage company as a back-end Tech Lead and was tasked with developing a PHP web framework to replace the dated and abominable system they currently had in place.  Their current &#8220;framework&#8221; was like the ugly bastard child of an <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC</a> with grade three burns.  In other words it was total shit (all these years later and I still seem to harbor a great hate for it).  The web had been advancing quite nicely and we were now looking at the birth of Web 2.0, so not only was it a misery for us developers to code in the current system, but it had now become a hindrance on what we were able to accomplish.  So management finally understood the necessity to invest in a new system and I was charged with leading it&#8217;s development, I was finally able to realize a vision for a framework I&#8217;d been dreaming up for a while.</p>
<p>The first step of course was to come up with a cool name for the framework.  After much brainstorming with the front-end Tech Lead (who was the co-creator of the framework) we finally came up with a name we both agreed on &#8211; Skeletor &#8211; not only a powerful villain from one of my favorite childhood toy franchises, but the name just seemed so damn appropriate for a framework.  I was super excited with the name and the project, and I wanted everyone else to get on board and be as excited as I was.  I also had the vision that the framework would belong to a web suite and comprise of various user interfaces to manage things like the URL catalog, error reporting, and debugging.</p>
<p>So the following is the very first piece of work I did for the project.  The document was put together before the project was completely sold to management and definitely helped seal the deal.  I also had the requirement to teach the rest of the team the fundamentals of OO programming and MVC frameworks.  So my idea here was that each member of the team would get a character from the MOTU world, which represented a module within the framework, and they would have to become that character and learn everything about the purpose of that character, and understand it well enough to present it to the rest of the team, and eventually develop-out their module.  In the end it was only two of us that were assigned to developing the framework, which we did and we did well, and that same framework now serves up over a half a dozen websites with over five million page impressions a month.  So this is just a mock-up for something that never really paned out as planed, in the end we never really fleshed out and finished what I was attempting here, but even still I think I came up with a really fresh approach to teaching the concepts of OO development, or teaching anything for that matter, and to this day I still look back and try to match that same vision I had then with the work I do now.  Enjoy!<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/motu.png" alt="" title="motu" width="400" height="119" class="aligncenter size-full wp-image-1629" /><br />
<span style="font-size: small;"><br />
The web systems suite comprises of everything involved in the website process:<br />
</span></p>
<ul>
<li>Framework</li>
<li>Framework Objects</li>
<li>CMS Application Interface</li>
</ul>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/skeletor.jpg" alt="" title="skeletor" width="200" height="153" class="alignleft size-full wp-image-1623" /><span style="font-weight: bold;">SKELETOR &#8211; The Framework</span></p>
<p>The framework for the web applications.  All applications live within an instance of the framework.  It consists of libraries, classes and run-time infrastructure.</p>
<ul>
<li>Logical and concise directory structure</li>
<li>Extends PEAR</li>
</ul>
<p><br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/he-man.jpg" alt="" title="he-man" width="200" height="153" class="alignright size-full wp-image-1616" /><span style="font-weight: bold;">I HAVE THE POWER &#8211; Master File</span></p>
<p>The master file for the SKELETOR framework. Mod rewrite points to this.</p>
<ul>
<li>Controls environment and global settings</li>
<li>Initializes common global objects</li>
<li>Routes, dispatches and renders the browser call</li>
</ul>
<p><br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/queen-marlena.jpg" alt="" title="queen-marlena" width="200" height="153" class="alignleft size-full wp-image-1621" /><span style="font-weight: bold;">QUEEN MARLENA &#8211; The Model</span></p>
<p>The model defines the properties of an object.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/eternia.jpg" alt="" title="eternia" width="200" height="153" class="alignright size-full wp-image-1614" /><span style="font-weight: bold;">ETERNIA &#8211; The View</span></p>
<p>The view contains all the output for the page call, with defined placeholders for logical driven content.  An object may have multiple views.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/king-randor.jpg" alt="" title="king-randor" width="200" height="153" class="alignleft size-full wp-image-1617" /><span style="font-weight: bold;">KING RANDOR &#8211; The Controller</span></p>
<p>The controller contains the default behaviour and helper classes of an object.  All Skeletor objects extend the Skeletor controller.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/evil-lyn.jpg" alt="" title="evil-lyn" width="200" height="153" class="alignright size-full wp-image-1615" /><span style="font-weight: bold;">EVIL-LYN &#8211; The Error Handler</span></p>
<p>The error handler takes care of where to log, and how to react to an error.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/trap-jaw.jpg" alt="" title="trap-jaw" width="200" height="153" class="alignleft size-full wp-image-1628" /><span style="font-weight: bold;">TRAP JAW &#8211; The Database Abstraction Layer</span></p>
<p>The database abstraction layer sits between the framework and the databases and handles all queries and results.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/man-at-arms.jpg" alt="" title="man-at-arms" width="200" height="153" class="alignright size-full wp-image-1618" /><span style="font-weight: bold;">MAN-AT-ARMS &#8211; The Security Layer</span></p>
<p>The security layer controls access and permissions for the user.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/battle-cat.jpg" alt="" title="battle-cat" width="200" height="153" class="alignleft size-full wp-image-1612" /><span style="font-weight: bold;">BATTLE CAT &#8211; The Content Catalog</span></p>
<p>The content catalog is both a CMS interface and a stored representation the its data.  It defines what view and model a URL should dispatch.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/ram-man.jpg" alt="" title="ram-man" width="200" height="153" class="alignright size-full wp-image-1622" /><span style="font-weight: bold;">RAM MAN &#8211; The Forms Catalog</span></p>
<p>The forms catalog is a CMS interface used to build the web forms and define how the captured data is stored.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/castle-grayskull.jpg" alt="" title="castle-grayskull" width="200" height="153" class="alignleft size-full wp-image-1613" /><span style="font-weight: bold;">CASTLE GRAYSKULL &#8211; The Session Handler</span></p>
<p>The session handler controls how session data is stored (e.g. serializing objects) and where it is stored to (e.g. written to the file system or a database).<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/stratos.jpg" alt="" title="stratos" width="200" height="153" class="alignright size-full wp-image-1626" /><span style="font-weight: bold;">STRATOS &#8211; Redirect Handler</span></p>
<p>The redirect object handles how all the various possible redirect types are handled.  It will consult with the content catalog to know how to handle a URL redirect (301 moved permanently, 302 temporarily redirected, etc.)<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/teela.jpg" alt="" title="teela" width="200" height="153" class="alignleft size-full wp-image-1627" /><span style="font-weight: bold;">TEELA &#8211; Form Handler</span></p>
<p>The form handler consults with the Forms Catalog<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/panthor.jpg" alt="" title="panthor" width="200" height="153" class="alignright size-full wp-image-1620" /><span style="font-weight: bold;">PANTHOR &#8211; The Request Dispatcher</span></p>
<p>Consults the catalogue hash map and calls the appropriate object.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/sorceress.jpg" alt="" title="sorceress" width="200" height="153" class="alignleft size-full wp-image-1625" /><span style="font-weight: bold;">SORCERESS &#8211; The AJAX Handler</span></p>
<p>Enables a page to speak telepathically with the server.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/snake-mountain.jpg" alt="" title="snake-mountain" width="200" height="153" class="alignright size-full wp-image-1624" /><span style="font-weight: bold;">SNAKE MOUNTAIN &#8211; The Skeletor Control Center</span></p>
<p>GUI to configure and control many core aspects of the framework.</p>
<ul>
<li>Generates new applications</li>
<li>Control user access</li>
<li>Control error handling</li>
</ul>
<p><br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/tri-klops.jpg" alt="" title="tri-klops" width="200" height="153" class="alignleft size-full wp-image-1611" /><span style="font-weight: bold;">TRI-KLOPS &#8211; The Search API</span></p>
<p>The search appliance interface.<br />
<br style="clear:both;"><br />
<img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/10/orko.jpg" alt="" title="orko" width="200" height="153" class="alignright size-full wp-image-1619" /><span style="font-weight: bold;">ORKO &#8211; Documentation System<br />
</span><br />
This represents the importance of both automatically generated code documents (PHPDocs), and manually generated user-friendly documentation (HOWTOs).<br />
<br style="clear:both;"></p>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/10/masters-of-the-universe-a-web-systems-suite/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Comic Effect using PHP GD</title>
		<link>http://pixelsfromtheedge.com/2009/06/comic-effect-using-php-gd/</link>
		<comments>http://pixelsfromtheedge.com/2009/06/comic-effect-using-php-gd/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 00:25:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Apps]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=29</guid>
		<description><![CDATA[For some reason I decided I wanted to create a comic-ized image of myself from a photo.  I think initially I wanted it to create myself some sort of digital avatar, but in the end it was out of pure obsession.  See I figured it was a really normal thing to want to do and I&#8217;d find a bunch of free websites out there where I could upload a photo of myself and it would convert it.  Not so (admittedly I was searching from &#8216;comicize&#8217; when I think the correct term is more like &#8216;posterize&#8217;), there are some sites out&#8230;]]></description>
			<content:encoded><![CDATA[<p>For some reason I decided I wanted to create a comic-ized image of myself from a photo.  I think initially I wanted it to create myself some sort of digital avatar, but in the end it was out of pure obsession.  See I figured it was a really normal thing to want to do and I&#8217;d find a bunch of free websites out there where I could upload a photo of myself and it would convert it.  Not so (admittedly I was searching from &#8216;comicize&#8217; when I think the correct term is more like &#8216;posterize&#8217;), there are some sites out there that do it but they&#8217;re pretty lame.  In my mind I was looking to do something along the lines of <a href="http://www.imdb.com/title/tt0405296/mediaindex" target="_new">A Scanner Darkly</a> to a photo of myself.  I was so convinced it was such a normal thing to want to do that I started researching how to do it in code.  There&#8217;s a lot of websites out there explaining how to do it in Photoshop but nothing in code.  So after an hour reacquainting myself with the <a href="http://www.php.net/manual/en/book.image.php" target="_new">PHP GD library</a> I was all set and ready to do it, and I realized I didn&#8217;t have a clue how to actually achieve this.  So after some messing around I came to the conclusion that GD just isn&#8217;t powerful enough, and there&#8217;s something new called <a href="http://www.php.net/manual/en/book.imagick.php" target="_new">ImageMagick</a> that is way more powerful and seems like it really has the capabilities to pull something like this off.  Except it&#8217;s not really available for Windows yet and it isn&#8217;t installed on my Linux box, and I&#8217;m way too impatient to switch gears and work on getting it installed before I continue of my quest to comicize a photo.  So I found <a href="http://fxdesigning.com/comic.php" target="_new">this tutorial</a> which is showing how to achieve the look in some old software, it seems to do a fairly good job at a basic level, so I figured if I could replicate that in PHP I&#8217;d at least satisfy myself for the time being.</p>
<p><span style="font-weight: bold;">Step 1</span><br />
Just as the tutorial says, the first step is to open the image.</p>
<pre class="brush: php;">&lt;?php
$imgName="beard.jpg";
$imgSource = imagecreatefromjpeg($imgName);
?&gt;</pre>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/06/beard.jpg" alt="" title="beard" width="300" height="400" class="aligncenter size-full wp-image-1727" /></p>
<p><span style="font-weight: bold;">Step 2</span><br />
The second step is to create the black and white canvas, using getimagesize() to size it to the original photo.</p>
<pre class="brush: php;">&lt;?php
list($w,$h)=getimagesize($imgName);
$imgK=imagecreatetruecolor($w,$h);
?&gt;</pre>
<p><span style="font-weight: bold;">Step 3</span><br />
The third step is the most complicated.  Unlike the application used in the tutorial which has a nice interface, we have to create the code to do this ourselves. We loop through every pixel of the source image and compare its tone.  This was the only variable in the code I had to tweak to match the example image in the tutorial.  The RGB sum image can add up to a total of 765 (255*3).  I played around and found that 300 was pretty much an exact match to the &#8220;Threshold Level&#8221; of 104 called out in the tutorial, this value may change depending on the contrast of the source image.  So in the code if the sum of the RGB value is above 300 we allocate a white pixel to the coordinate, otherwise we allocate to it a black pixel.</p>
<pre class="brush: php;">&lt;?php
for($y=0;$y&lt;$h;$y++){
  for($x=0;$x&lt;$w;$x++){
    $rgb = imagecolorat($imgSource, $x, $y);
    $r = ($rgb &gt;&gt; 16) &amp; 0xFF;
    $g = ($rgb &gt;&gt; 8) &amp; 0xFF;
    $b = $rgb &amp; 0xFF;
    $bw=$r+$g+$b&gt;300?imagecolorallocate($imgK,255,255,255):imagecolorallocate($imgK,0,0,0);
    imagesetpixel($imgK,$x,$y,$bw);
  }
}
?&gt;</pre>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/06/beardk.png" alt="" title="beardk" width="300" height="400" class="aligncenter size-full wp-image-1728" /></p>
<p><span style="font-weight: bold;">Step 4</span><br />
Just like in the tutorial, in step 4 we merge the black and white image over the original with an opacity of 40%.  We&#8217;ll also use this step to write out the image to the browser (sending the correct headers also).</p>
<pre class="brush: php;">&lt;?php
imagecopymerge($imgSource,$imgK,0,0,0,0,$w,$h,40);
header("Content-type: image/png");
imagepng($imgSource);
?&gt;</pre>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/06/beardnew.png" alt="" title="beardnew" width="300" height="400" class="aligncenter size-full wp-image-1726" /></p>
<p>The dark shadows help give the image more shading, and the white layer helps smudge and tone down the number of colors that the original photo had, both of which contribute to a more comic-ish effect.  It&#8217;s worked out quite well with this image when using the exact same settings as created replicating the tutorial, but testing it out on other images it&#8217;s obvious it all needs to be adjusted on a case by case basis, and as the tutorial points out, this technique only really works well with faces.</p>
<p>Anyways this has been a taste at something I&#8217;ve never tried before. For a long time I&#8217;ve thought about what makes up an image, where the light and colors come from and how they all work together to make or break and image.  It&#8217;s all very interesting and I am eager to pickup Photoshop and really start learning how to do some usefull effects, and install imageMagick and replicate what I&#8217;ve learnt in my code.</p>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/06/comic-effect-using-php-gd/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Geocoding Part 2 &#8211; Import your own Zip Code Spatial Database</title>
		<link>http://pixelsfromtheedge.com/2009/04/geo-coding-part-2-import-your-own-zip/</link>
		<comments>http://pixelsfromtheedge.com/2009/04/geo-coding-part-2-import-your-own-zip/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 10:48:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=23</guid>
		<description><![CDATA[In my <a href="http://richie-p.com/blog/2009/04/geocoding-and-distancing-and-latitude/">post yesterday</a> I talked about calculating geographical distances.  During my research I’d come across this <a href="http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL" target="_new">http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL</a>.  It was a super interesting read and helped me get a much better understanding of what it is I am even doing.]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.pixelsfromtheedge.com/2009/04/geocoding-and-distancing-and-latitude/">post yesterday</a> I talked about calculating geographical distances.  During my research I’d come across this <a href="http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL" target="_new">http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL</a>.  It was a super interesting read and helped me get a much better understanding of what it is I am even doing.  Also it really helps you gets super optimized with the whole subject, but as the locations table I am working with has less than 3000 entries my queries were already coming back super fast in less than 1000th of a second, so it really didn’t need to be optimized more.  I didn’t really have time to mess around and investigate it all, and seeing as I still didn’t really fully understand the whole subject too well it was something I’d come back to at another time if need be.  However it did point me to <a href="http://www.geonames.org/" target="_new">geonames.org</a> that has free databases with geographical data to download.  This is incredibly useful and whenever I’ve needed this data in the past I’ve had my client buy it (the disk is like $30 so no biggie, but it seems this might even be the free source they are pulling it all from).  They have individual country zip codes files available to <a href="http://download.geonames.org/export/zip/" target="_new">export</a>, the US file contains exactly what I needed – all the US zip codes with their respective latitude and longitude coordinates.  This site has a whole range of useful features on the subject – they appear to even have their own <a href="http://www.geonames.org/export/web-services.html" target="_new">webservice</a>, and a list client libraries in various languages, which pointed me towards a <a href="http://www.solmetra.com/en/disp.php/en_products/en_scripts/en_maps" target="_new">PHP library</a> that appears to be doing a lot of what I need (but also way more than what I need), but by this point I already have everything I needed and had already spent too much time on the subject (not really but I didn’t have as much time allocated to the subject as it really needs – geo-location is a subject unto itself but only a small piece of the website I am building).</p>
<p>So geonames.org offers a free webservice, but I was already using the google API which is also free so I didn’t see any benefit to switch.  But they did offer for free all the zip codes with the geographical coordinates so I decided to import this into my database and cut out the 3rd party google Geocode API.  It would mean quicker response time and not having to worry about if the service is unavailable or returning errors, I was actually planning to cache the results locally anyway.  And perhaps the zip code table might have to be updated on an annual basis to maintain its accuracy (like do zip codes really change that much anyways?), but the web service API is subject to change and it would be less maintainable to monitor it and react to the changes.</p>
<p>So I downloaded the tab delimited US Zip Codes file and imported it into a table in my database called “tbl_Zipcodes_Spatial”, with the following fields (from the included readme):</p>
<p class="reverse">
Country_code      : iso country code, 2 characters<br />
Postal_code       : varchar(10)<br />
Place_name        : varchar(180)<br />
Admin_name1       : 1. order subdivision (state) varchar(100)<br />
Admin_code1       : 1. order subdivision (state) varchar(20)<br />
Admin_name2       : 2. order subdivision (county/province) varchar(100)<br />
Admin_code2       : 2. order subdivision (county/province) varchar(20)<br />
Admin_name3       : 3. order subdivision (community) varchar(100)<br />
Latitude          : estimated latitude (wgs84) float(10,6)<br />
Longitude         : estimated longitude (wgs84) float(10,6)<br />
Accuracy          : accuracy of lat/lng from 1=estimated to 6=centroid
</p>
<p>I created an index on the postal_code field and updated my GeoPos:: prepareGetByDistanceSQL() method to get the zip code from the new table.  I actually created a new method so that the class still has the ability to pass in the coordinates to the old method when necessary:</p>
<pre class="brush: php;">
&lt;?php
function prepareGetByDistanceWithZipcodeSQL($zip_code,$distance,$table_name,$fields,$units="miles"){
  $cUnit=self::convertMeasuringUnit($units);
  $sql="
    SELECT ".$table_name.".".implode($fields,",".$table_name.".").",
      tbl_zipcodes_spatial.Latitude AS Zipcode_Latitude,
      tbl_zipcodes_spatial.Longitude AS Zipcode_Longitude,
      ACOS(SIN( PI()* tbl_zipcodes_spatial.Latitude /180 )*SIN( PI()*".$table_name.".Latitude/180 ))+(COS(PI()* tbl_zipcodes_spatial.Latitude /180)*COS( PI()*".$table_name.".Latitude/180) *COS(PI()*".$table_name.".Longitude/180-PI()* tbl_zipcodes_spatial.Longitude /180))* ".$cUnit." AS Distance
    FROM tbl_zipcodes_spatial,".$table_name."
    WHERE
      tbl_zipcodes_spatial.postal_code='".$zip_code."'
      AND ".$cUnit." * ACOS( (SIN(PI()* tbl_zipcodes_spatial.Latitude /180)*SIN(PI() * ".$table_name.".Latitude/180)) +
        (COS(PI()* tbl_zipcodes_spatial.Latitude /180)*COS(PI()*".$table_name.".Latitude/180)*COS(PI() * ".$table_name.".Longitude/180-PI()* tbl_zipcodes_spatial.Longitude /180))
        ) &lt;= ".$distance."
    ORDER BY ".$cUnit." * ACOS(
      (SIN(PI()* tbl_zipcodes_spatial.Latitude /180)*SIN(PI()*".$table_name.".Latitude/180)) +
        (COS(PI()* tbl_zipcodes_spatial.Latitude /180)*COS(PI()*".$table_name.".Latitude/180)*COS(PI() * ".$table_name.".Longitude/180-PI()* tbl_zipcodes_spatial.Longitude /180))
      )
  ";
  return $sql;
}
?&gt;
</pre>
<p>And it worked!  Barely increased the query execution time, and I’ve completely cut out the google API middle man so the overall execution time of the page is greatly increased.  Now I feel like I’ve put together something pretty damn robust (the final touch would be to create a stored procedure in the database, and this is something I&#8217;ll come back to at a future point).  Behold the final script:</p>
<pre class="brush: php;">
&lt;?php
/*
Geographical Location functions
ALL CREDIT GOES TO http://blog.peoplesdns.com/
Thanks to these two blog posts:

http://blog.peoplesdns.com/archives/24

http://blog.peoplesdns.com/archives/34

This API:

http://code.google.com/apis/maps/documentation/geocoding/

And the zipcode database found here:

http://www.geonames.org/

*/

class GeoLoc{

	const GOOGLE_API_KEY="yourgooglekeygoeshere";
	const GOOGLE_API_URL="http://maps.google.com/maps/geo";

	/*
	queries the google api for zip code
	returns long and lat coordinates
	*/
	public function getZipcodeCoordinates($zip_code){
		$result=file_get_contents(self::GOOGLE_API_URL."?q=".$zip_code."&#038;sensor=false&#038;gl=us&#038;output=xml&#038;key=".self::GOOGLE_API_KEY);
		$data=simplexml_load_string($result);
		$coord=$data-&gt;Response-&gt;Placemark-&gt;Point-&gt;coordinates;
		$coord=explode(",",$coord);
		$r-&gt;longitude=$coord[0];
		$r-&gt;latitude=$coord[1];
		return $r;
	}

	/*
	returns the radius
	*/
	public function rad($v){
		return ($v*M_PI/180);
	}

	/*
	degree,minute,seconds to decimal degrees
	note: this could also be done in a single line using ternary
	*/
	public function dms2deg($D,$M,$S,$dir){
		if(strpos(' WsSs', $dir)&gt;0){
			return(-1 * ($D + ($M + $S/60)/60));
		}else{
			return($D + ($M + $S/60)/60);
		}
	}

	/*
	degree,minute,seconds
	*/
	public function dms($rad) {
		$d = abs($rad * 180 / M_PI);
		$d += 1/7200; // add ½ second for rounding
		$deg = floor($d);
		$min = floor(($d-$deg)*60);
		$sec = floor(($d-$deg-$min/60)*3600);
		// add leading zeros if required
		if ($deg&lt; 100) $deg = '0' + $deg;
		if ($deg&lt; 10) $deg = '0' + $deg;
		if ($min&lt; 10) $min = '0' + $min;
		if ($sec&lt; 10) $sec = '0' + $sec;
		return $deg + '\u00B0' + $min + '\u2032' + $sec + '\u2033';
	}

	/*
	gets the measuring unit
	*/
	public function convertMeasuringUnit($units){
		switch ($units){
			case "miles": $r = 3963.191; break;;
			case "nmiles": $r = 3441.596; break;;
			case "kilo": $r = 6378.137; break;;
		}
		return $r;
	}

	/*
	distance between two points using sherical law of cosines
	cos c = cos a cos b + sin a sin b cos C
	*/
	public function distance($lat1, $lon1, $lat2, $lon2, $units = 'miles'){
		$lat1 = self::rad($lat1); $lon1 = self::rad($lon1);
		$lat2 = self::rad($lat2); $lon2 = self::rad($lon2);
		$r=self::convertMeasuringUnit($units);

		return acos(sin($lat1)*sin($lat2) + cos($lat1)*cos($lat2)*cos($lon2-$lon1)) * $r;
	}

	/*
	initial bearing from point 1 to point 2
	*/
	public function bearing($lat1,$lon1, $lat2, $lon2) {
		$y = sin($lon2-$lon1) * cos($lat2);
		$x = cos($lat1)*sin($lat2) - sin($lat1)*cos($lat2)*cos($lon2-$lon1);
		return atan2($y, $x);
	}

	/*
	find out what the midpoint between two points is
	*/
	public function midpoint($lat1, $lon1, $lat2, $lon2) {
		$lat1 = self::rad($lat1); $lon1 = self::rad($lon1);
		$lat2 = self::rad($lat2); $lon2 = self::rad($lon2);
		$dLon = $lon2 - $lon1;
		$Bx = (cos($lat2) * cos($dLon));
		$By = (cos($lat2) * sin($dLon));
		$lat3 = atan2( sin($lat1) + sin($lat2), sqrt( (cos($lat1)+$Bx) * (cos($lat1)+$Bx) + ($By * $By)) );
		$lon3 = $lon1 + atan2($By, cos($lat1) + $Bx);

		if (!$lat3 || !$lon3) return false;
		return array($lat3 * 180 / M_PI, $lon3 * 180 / M_PI);
	}

	/*
	returns sql to query a table for rows by distance (miles,nmiles,kilo)
	table must contain fields named latitude and longitude
	*/
	public function prepareGetByDistanceSQL($long,$lat,$distance,$table_name,$fields,$units="miles"){
		$cUnit=self::convertMeasuringUnit($units);
		$sql="
			SELECT ".implode($fields,",").",
				acos(SIN( PI()* ".$lat." /180 )*SIN( PI()*latitude/180 ))+(cos(PI()* ".$lat." /180)*COS( PI()*latitude/180) *COS(PI()*longitude/180-PI()* ".$long." /180))* ".$cUnit." AS distance
			FROM ".$table_name."
			WHERE active=1
				AND ".$cUnit." * ACOS( (SIN(PI()* ".$lat." /180)*SIN(PI() * latitude/180)) +
				(COS(PI()* ".$lat." /180)*cos(PI()*latitude/180)*COS(PI() * longitude/180-PI()* ".$long." /180))
				) &lt;= ".$distance."
			ORDER BY ".$cUnit." * ACOS(
				(SIN(PI()* ".$lat." /180)*SIN(PI()*latitude/180)) +
				(COS(PI()* ".$lat." /180)*cos(PI()*latitude/180)*COS(PI() * longitude/180-PI()* ".$long." /180))
			)
		";
		return $sql;
	}

	/*
	returns sql to query a table for rows by distance (miles,nmiles,kilo)
	table must contain fields named latitude and longitude
	requires you have the tbl_zipcodes_spatial table http://download.geonames.org/export/zip/
	*/
	public function prepareGetByDistanceWithZipcodeSQL($zip_code,$distance,$table_name,$fields,$units="miles"){
		$cUnit=self::convertMeasuringUnit($units);
		$sql="
			SELECT ".$table_name.".".implode($fields,",".$table_name.".").",
				tbl_zipcodes_spatial.Latitude AS Zipcode_Latitude,
				tbl_zipcodes_spatial.Longitude AS Zipcode_Longitude,
				ACOS(SIN( PI()* tbl_zipcodes_spatial.Latitude /180 )*SIN( PI()*".$table_name.".Latitude/180 ))+(COS(PI()* tbl_zipcodes_spatial.Latitude /180)*COS( PI()*".$table_name.".Latitude/180) *COS(PI()*".$table_name.".Longitude/180-PI()* tbl_zipcodes_spatial.Longitude /180))* ".$cUnit." AS Distance
			FROM tbl_zipcodes_spatial,".$table_name."
			WHERE
				tbl_zipcodes_spatial.postal_code='".$zip_code."'
				AND ".$cUnit." * ACOS( (SIN(PI()* tbl_zipcodes_spatial.Latitude /180)*SIN(PI() * ".$table_name.".Latitude/180)) +
				(COS(PI()* tbl_zipcodes_spatial.Latitude /180)*COS(PI()*".$table_name.".Latitude/180)*COS(PI() * ".$table_name.".Longitude/180-PI()* tbl_zipcodes_spatial.Longitude /180))
				) &lt;= ".$distance."
			ORDER BY ".$cUnit." * ACOS(
				(SIN(PI()* tbl_zipcodes_spatial.Latitude /180)*SIN(PI()*".$table_name.".Latitude/180)) +
				(COS(PI()* tbl_zipcodes_spatial.Latitude /180)*COS(PI()*".$table_name.".Latitude/180)*COS(PI() * ".$table_name.".Longitude/180-PI()* tbl_zipcodes_spatial.Longitude /180))
			)
		";
		return $sql;
	}
}
?&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/04/geo-coding-part-2-import-your-own-zip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Geocoding and Distancing and Latitude and Longitude and umm Stuff</title>
		<link>http://pixelsfromtheedge.com/2009/04/geo-coding-and-distancing-and-latitude/</link>
		<comments>http://pixelsfromtheedge.com/2009/04/geo-coding-and-distancing-and-latitude/#comments</comments>
		<pubDate>Thu, 23 Apr 2009 19:01:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[Google API]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=22</guid>
		<description><![CDATA[Okay this is complicated stuff.  Working on putting together a new site for a client, I have a table of locations with longitude and latitude fields for every row (I actually had a tab delimited file, but I sucked it into the db).  For the functionality on the web front end a user needs to search by distance, e.g. find all locations within 10 miles of a zip code.  Um okay, so how the hell do I do this?
Well first of I need to get the latitude and longitude for a zip code.  For that I very quickly found&#8230;]]></description>
			<content:encoded><![CDATA[<p>Okay this is complicated stuff.  Working on putting together a new site for a client, I have a table of locations with longitude and latitude fields for every row (I actually had a tab delimited file, but I sucked it into the db).  For the functionality on the web front end a user needs to search by distance, e.g. find all locations within 10 miles of a zip code.  Um okay, so how the hell do I do this?</p>
<p>Well first of I need to get the latitude and longitude for a zip code.  For that I very quickly found the <a href="http://code.google.com/apis/maps/documentation/geocoding/" target=_new>Google Geocode API</a> and threw together the following:</p>
<pre class="brush: php;">
&lt;?php
$result=file_get_contents("http://maps.google.com/maps/geo?48220&amp;sensor=false&amp;gl=us&amp;output=xml&amp;key=yourgooglekey);
$data=simplexml_load_string($result);
$coord=$data->Response->Placemark->Point->coordinates;
$coord=explode(",",$coord);
$longitude=$coord[1];
$latitude=$coord[0];
?&gt;
</pre>
<p>It took like 10 minutes, and that included signing up for the API key and reading the documentation, shit this geocoding stuff is easy, I should be done by lunch…</p>
<p>Yeah okay so I have two sets of coordinates, great but errr now what?  So I find the <a href="http://en.wikipedia.org/wiki/Haversine_formula" target=_new>Haversine</a> formula, but alas not really being any good at math I don’t understand it, but it doesn’t really matter because I know how to convert it to do the math in PHP.  Cool so I got the Haversine function in PHP now but how do I query it against the data in my database?  I’d read some stuff about geographical libraries for databases and it seemed super complicated, like the <a href="http://dev.mysql.com/tech-resources/articles/4.1/gis-with-mysql.html" target=_new>GIS and Spatial extensions for MySQL</a>.  So I figure I’ll use a two step approach and do a simple query to pull out a square block of locations and then apply the math.  i.e. if I am searching for within a 10 mile radius of a location I’ll do a search on -10 miles and +10 miles, but as the distance is circular I would be getting results in the four corners of that square block that are greater than the 10 miles, and I would then apply the Haversine function and be left only with those results that where truly within the 10 mile radius.</p>
<p>By sheer luck I found <a href="http://blog.peoplesdns.com/archives/24" target=_new>this post</a>.  It was insane, I didn’t realize you could apply the Haversine formula directly in SQL, I ran that query in my db and bam it worked instantly (well actually there’s a typo syntax error ‘< =’ -blank space between the less than and equals character - in the where clause).  Obviously I had to switch out a couple of things so it played nice with my database, but it was instant success, I tried out some different latitude and longitude coordinates and it worked every time:</p>
<p class="reverse">
SELECT Name,Address,Address2,City,State,Zip,Phone,URL,Latitude,Longitude,<br />    acos(SIN( PI()* 42.4584036 /180 )*SIN( PI()*latitude/180 ))+(cos(PI()* 42.4584036 /180)*COS( PI()*latitude/180) *COS(PI()*longitude/180-PI()* -83.1380955 /180))* 3963.191 AS distance<br />   FROM tbl_retailers<br />   WHERE active=1<br />    AND 3963.191 * ACOS( (SIN(PI()* 42.4584036 /180)*SIN(PI() * latitude/180)) +<br />    (COS(PI()* 42.4584036 /180)*cos(PI()*latitude/180)*COS(PI() * longitude/180-PI()* -83.1380955 /180))<br />    ) <= 100    ORDER BY 3963.191 * ACOS(     (SIN(PI()* 42.4584036 /180)*SIN(PI()*latitude/180)) +     (COS(PI()* 42.4584036 /180)*cos(PI()*latitude/180)*COS(PI() * longitude/180-PI()* -83.1380955 /180))    )
</p>
<p>Wow so this was it, everything I needed.  Oh wait, except that I needed to display the distance in miles.  But the guy who blogged this was some kind of superman and he talks about this on <a href="http://blog.peoplesdns.com/archives/34" target=_new>another post</a>.  Really I only needed the rad() and distance() functions (because distance is dependent on rad), but I decided that they’ll probably all come in useful one day, so I took them wrapped them in a class called GeoLoc.  The class doesn’t need to be instantiated into an object so all methods can be called as follows</p>
<pre class="brush: php;">
&lt;?php
GeoLoc::distance($lat1, $lon1, $lat2, $lon2, $units);
?&gt;
</pre>
<p>Then decided I could abstract in the SQL statement by passing in all necessary variables, and I added it to the class:</p>
<pre class="brush: php;">
&lt;?php
GeoLoc::prepareGetByDistanceSQL($lat,$long,$distance_in_miles,$table_name,$fields);
?&gt;
</pre>
<p>I then understood that the measuring unit the query is using is the same as in the distance() method so I abstracted it out into its own method.  At which point I noticed that the numbers didn’t match exactly – for miles the SQL had 3963.191 whereas the distance function only had 3963.1.  I decided that the SQL query had the more granular number and when I reviewed its original blog post it was across the board for all three measuring units so I updated all the numbers.  I then figured I might as well abstract in the Google Geocode zip code lookup.</p>
<p>This is what I was left with (functions I&#8217;m not using removed); I give all credit to joeldg:</p>
<pre class="brush: php;">
&lt;?php
/*
Geographical Location functions
ALL CREDIT GOES TO http://blog.peoplesdns.com/
Thanks to these two blog posts:

http://blog.peoplesdns.com/archives/24

http://blog.peoplesdns.com/archives/34

This API:

http://code.google.com/apis/maps/documentation/geocoding/

*/
class GeoLoc{

const GOOGLE_API_KEY="yourkeygoeshere";
const GOOGLE_API_URL="http://maps.google.com/maps/geo";

/*
queries the google api for zip code
returns long and lat coordinates
*/
function getZipcodeCoordinates($zip_code){
  $result=file_get_contents(self::GOOGLE_API_URL."?q=".$zip_code."&#038;sensor=false&#038;gl=us&#038;output=xml&#038;key=".self::GOOGLE_API_KEY);
  $data=simplexml_load_string($result);
  $coord=$data-&gt;Response-&gt;Placemark-&gt;Point-&gt;coordinates;
  $coord=explode(",",$coord);
  $r-&gt;longitude=$coord[0];
  $r-&gt;latitude=$coord[1];
  return $r;
}
function rad($v){
  return ($v*M_PI/180);
}
/*
distance between two points using sherical law of cosines
cos c = cos a cos b + sin a sin b cos C
*/
function distance($lat1, $lon1, $lat2, $lon2, $units = 'miles'){
  $lat1 = self::rad($lat1); $lon1 = self::rad($lon1);
  $lat2 = self::rad($lat2); $lon2 = self::rad($lon2);
  $r=self::convertMeasuringUnit($units);
  return acos(sin($lat1)*sin($lat2) + cos($lat1)*cos($lat2)*cos($lon2-$lon1)) * $r;
}
/*
gets the measuring unit
*/
function convertMeasuringUnit($units){
  switch ($units){
    case "miles": $r = 3963.191; break;;
    case "nmiles": $r = 3441.596; break;;
    case "kilo": $r = 6378.137; break;;
  }
  return $r;
}
/*
returns sql to query a table for rows by distance (miles,nmiles,kilo)
table must contain fields named latitude and longitude
*/
function prepareGetByDistanceSQL($long,$lat,$distance,$table_name,$fields,$units="miles"){
  $cUnit=self::convertMeasuringUnit($units);
  $sql="
    SELECT ".implode($fields,",").",
    acos(SIN( PI()* ".$lat." /180 )*SIN( PI()*latitude/180 ))+(cos(PI()* ".$lat." /180)*COS( PI()*latitude/180) *COS(PI()*longitude/180-PI()* ".$long." /180))* ".$cUnit." AS distance
    FROM ".$table_name."
    WHERE active=1
      AND ".$cUnit." * ACOS( (SIN(PI()* ".$lat." /180)*SIN(PI() * latitude/180)) +
    (COS(PI()* ".$lat." /180)*cos(PI()*latitude/180)*COS(PI() * longitude/180-PI()* ".$long." /180))
    ) &lt;= ".$distance."
    ORDER BY ".$cUnit." * ACOS(
    (SIN(PI()* ".$lat." /180)*SIN(PI()*latitude/180)) +
    (COS(PI()* ".$lat." /180)*Cos(PI()*latitude/180)*COS(PI() * longitude/180-PI()* ".$long." /180))
   )
  ";
  return $sql;
}
}
?&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/04/geo-coding-and-distancing-and-latitude/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Customizing WordPress as a CMS finishing touches</title>
		<link>http://pixelsfromtheedge.com/2009/04/customizing-wordpress-as-cms-finishing-touches/</link>
		<comments>http://pixelsfromtheedge.com/2009/04/customizing-wordpress-as-cms-finishing-touches/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 17:00:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=21</guid>
		<description><![CDATA[My last couple of posts I've talked about how to customize Wordpress to create your own theme and templates.  As I talked about in <a href="http://richie-p.com/blog/2009/03/using-wordpress-as-custom-cms.html">this post</a> I feel that Wordpress is a hugely powerful CMS admin system but falls behind with its front-end publishing capabilities.  I don't like how it publishes the HTML and in this post I will give some hints as to how to completely abandon the Wordpress front-end for your own.]]></description>
			<content:encoded><![CDATA[<p>My last couple of posts I&#8217;ve talked about how to customize WordPress to create your own theme and templates.  As I talked about in <a href="http://www.pixelsfromtheedge.com/2009/03/using-wordpress-as-custom-cms.html">this post</a> I feel that WordPress is a hugely powerful CMS admin system but falls behind with its front-end publishing capabilities.  I don&#8217;t like how it publishes the HTML and in this post I will give some hints as to how to completely abandon the WordPress front-end for your own.</p>
<p><span style="font-weight: bold;">Custom Permalinks</span><br />By default all pages are created as something like &#8216;http://www.mysite.com/?p=14&#8242;.  But WordPress has it&#8217;s own built-in URL parser and router allowing us to make pretty URLs.  Click &#8216;Settings->Permalinks&#8217; in the left sidebar and select the &#8216;Month and name&#8217; radio button and hit save (don&#8217;t worry about the other options, they really only affect the &#8220;posts&#8221; URL structure and we&#8217;re only concentrating on &#8220;pages&#8221; here).</p>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/04/image001.png" alt="" title="image001" width="400" height="250" class="aligncenter size-full wp-image-1773" /></p>
<p>It creates an &#8216;.htaccess&#8217; file in the web root, if Apache doesn&#8217;t have permission to create this file then you can create it yourself with the following:</p>
<p class="reverse"># BEGIN WordPress<br /><ifmodule c=""><br />RewriteEngine On<br />RewriteBase /<br />RewriteCond %{REQUEST_FILENAME} !-f<br />RewriteCond %{REQUEST_FILENAME} !-d<br />RewriteRule . /index.php [L]<br /></ifmodule><br /># END WordPress</p>
<p>Basically every file that doesn&#8217;t exist (media, css, js, etc. files that physically exist bypass the rule) gets sent to the index.php file which does a URL lookup and routes to the correct template.</p>
<p>You can now go and look at a custom page you&#8217;ve made and see it has a beautified URL as a <span style="font-style: italic;">Permalink</span>.</p>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/04/image003.png" alt="" title="image003" width="400" height="250" class="aligncenter size-full wp-image-1771" /></p>
<p><span style="font-weight: bold;">Custom Header and Footer</span><br />The default WordPress header and footer does a lot of automatic work.  In order to free your code from this I recommend creating you own header and footer.  Any functionality that the header and footer contains that you want to keep can be ported over as you need it.</p>
<p>In your theme folder create your own header.php and footer.php files. It&#8217;s probably a good idea to save a backup first (even though you&#8217;ll probably already have the whole thing backed-up from when you created your own <a href="http://www.pixelsfromtheedge.com/2009/03/create-custom-wordpress-theme-in-one.html">theme</a>, and then get rid of everything in the files you don&#8217;t want.  For example when I first started experimenting I kept all the boiler plate stuff and ditched the automatic navigation generation and sidebar code.  Start with the minimum and work things back in from your template as you need them, if you feel you need them, personally I rewrote everything back in.</p>
<p>Once you understand what you&#8217;re doing here you can drop the whole header and footer approach and use a templating engine such as <a href="http://pear.php.net/package/HTML_Template_Sigma" target="_new">Sigma</a> (which I&#8217;ve favored for some time).</p>
<p><span style="font-weight: bold;">Custom Homepage</span><br />The final move is to set the homepage as something other that the blog.  This is the final key in freeing up WordPress from being a blog tool dependent on the default code to becoming, well anything you want from a website, backed by a powerful CMS.  Of course you will also always have the option to quickly and easily implement a powerful blogging system into your site, but the point is the blog doesn&#8217;t actually have to be your site.</p>
<p>In your admin panel create a new page with the title &#8216;HOMEPAGE&#8217;, I recommend to first create a homepage <a href="http://www.pixelsfromtheedge.com/2009/04/create-custom-template-in-wordpess.html">template</a> because a homepage is never like anything else.  Once you have that page published navigate to &#8216;Settings->Reading&#8217; and under the first option &#8216;Front page displays&#8217; select the second radio button &#8216;A static page (select below)&#8217;, and in the drop-down find the &#8216;HOMEPAGE&#8217; page you just created, and save your changes.</p>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/04/image005.png" alt="" title="image005" width="400" height="250" class="aligncenter size-full wp-image-1769" /></p>
<p>That&#8217;s it, you&#8217;re now free to go crazy with your website design and code yet still harness the power that the WordPress CMS yields!  And don&#8217;t forget if you want to have a blog in your website, now or in the future, you already have all the tools you could want.</p>
<p>This is part of an ongoing series of posts I am publishing talking about how to use WordPress as a custom CMS.</p>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/04/customizing-wordpress-as-cms-finishing-touches/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a custom template in Wordpess</title>
		<link>http://pixelsfromtheedge.com/2009/04/create-custom-template-in-wordpess/</link>
		<comments>http://pixelsfromtheedge.com/2009/04/create-custom-template-in-wordpess/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 13:15:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=20</guid>
		<description><![CDATA[<span style="font-weight: bold;">1.</span> Open up a new file and add the following:
<pre class="brush: php;">
&#60;?php
/*
Template Name: My Template
*/
?&#62;
</pre>
<span style="font-weight: bold;">2.</span> Save the file in your theme folder with the name of your new template, the filename doesn't have to be an exact match for the template name, e.g. 'mytemplate.php'.]]></description>
			<content:encoded><![CDATA[<p><span style="font-weight: bold;">1.</span> Open up a new file and add the following:</p>
<pre class="brush: php;">
&lt;?php
/*
Template Name: My Template
*/
?&gt;
</pre>
<p><span style="font-weight: bold;">2.</span> Save the file in your theme folder with the name of your new template, the filename doesn&#8217;t have to be an exact match for the template name, e.g. &#8216;mytemplate.php&#8217;.</p>
<p><span style="font-weight: bold;">3.</span> In the admin panel create a new page.  Give it a title, type in some content, and then in the right sidebar under &#8216;Attributes&#8217;, find your new template in the drop down and select it, and publish the page.</p>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/04/template1.png" alt="" title="template1" width="400" height="250" class="aligncenter size-full wp-image-1778" /></p>
<p><span style="font-weight: bold;">4.</span>  When you view your new page on your sites front-end you&#8217;ll see a totally blank page.  This is good and means it&#8217;s worked as we&#8217;ve not told the template to do anything yet.</p>
<p><span style="font-weight: bold;">5.</span>  Go back to your template file and update it to match the following:</p>
<pre class="brush: php;">
&lt;?php
/*
Template Name: My Template
*/
get_header();

get_footer();
?&gt;
</pre>
<p><span style="font-weight: bold;">6.</span>  Now when you refresh your new page you&#8217;ll see the header and footer are now incorporated:</p>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/04/template2.png" alt="" title="template2" width="400" height="250" class="aligncenter size-full wp-image-1779" /></p>
<p><span style="font-weight: bold;">7.</span> That&#8217;s great but the content from the CMS is still missing.  Add the following into the template file between the get_header() and get_footer() calls, save it and refresh the page:</p>
<pre class="brush: php;">
$thisPage=query_posts("pagename=".$_SERVER["PATH_INFO"]);
echo $thisPage[0]-&gt;post_content;
</pre>
<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/04/template3.png" alt="" title="template3" width="400" height="250" class="aligncenter size-full wp-image-1780" /></p>
<p>That&#8217;s it, you&#8217;ve just created your own template!  You can now continue to develop out your new template and create more pages using that template, and create more templates.</p>
<p>This is part of an ongoing series of posts I am publishing talking about how to use WordPress as a custom CMS.</p>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/04/create-custom-template-in-wordpess/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mashing up the Twitter API with PHP</title>
		<link>http://pixelsfromtheedge.com/2009/03/mashing-up-twitter-api-with-php/</link>
		<comments>http://pixelsfromtheedge.com/2009/03/mashing-up-twitter-api-with-php/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 23:44:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Twitter API]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=12</guid>
		<description><![CDATA[<pre class="brush: php;">&#60;?php
$username = "youraccountname";
$password = "yourpassword";
$url="http://twitter.com/statuses/friends/londonstreetlif.xml";
$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_USERPWD, "$username:$password");
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($curl, CURLOPT_URL, $url);
$result = curl_exec ($curl); //remove space before parenthesis
curl_close($curl);
?&#62;
</pre>]]></description>
			<content:encoded><![CDATA[<pre class="brush: php;">&lt;?php
$username = "youraccountname";
$password = "yourpassword";
$url="http://twitter.com/statuses/friends/londonstreetlif.xml";
$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_USERPWD, "$username:$password");
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($curl, CURLOPT_URL, $url);
$result = curl_exec ($curl); //remove space before parenthesis
curl_close($curl);
?&gt;
</pre>
<p>Now lets use SimpleXML to loop through the returned xml and create an array of my friends:</p>
<pre class="brush: php;">&lt;?php
$friendsArr=array();
$feed = simplexml_load_string($result);
foreach($feed-&gt;user AS $userXML){
   $user = simplexml_import_dom($userXML);
   $friendsArr[]=(string)$user-&gt;screen_name;
}
?&gt;
</pre>
<p>Lets assume we have done the same thing to create an array of my followers, now we can find everyone that I am friends with but doesn&#8217;t follow me:</p>
<pre class="brush: php;">&lt;?php
$badfriendsArr=array_diff($friendsArr,$followersArr);
?&gt;
</pre>
<p>And finally lets display, the lists are returned from Twitter in the order the relationship began from newest to oldest, so lets order alphabetically and print:</p>
<pre class="brush: php;">&lt;?php
natcasesort($badfriendsArr);
foreach($badfriendsArr AS $badfriend){
   echo "&lt;a href="http://www.twitter.com/$badfriend"&gt;$badfriend&lt;/a&gt;&lt;br&gt;";
}
?&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/03/mashing-up-twitter-api-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using WordPress as a custom CMS</title>
		<link>http://pixelsfromtheedge.com/2009/03/using-wordpress-as-custom-cms/</link>
		<comments>http://pixelsfromtheedge.com/2009/03/using-wordpress-as-custom-cms/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 14:58:00 +0000</pubDate>
		<dc:creator>Richie</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.detroitdigitalrevolution.com/clients/me/blog/?p=7</guid>
		<description><![CDATA[I recently had a crash course in WordPress when I had to build a very custom website from scratch in two weeks from start to finish.   It needed to be WordPress because this site will contain a blog that will be handed off to a third party to maintain, and WordPress is arguably the industry standards for blogging software.  I wasn&#8217;t overly familiar with WordPress, I&#8217;d setup a blog or two in my time, but never anything as complex as building a custom theme or plugin.  But I basically knew everything I needed to do was possible, I&#8217;d read up&#8230;]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.pixelsfromtheedge.com/wp-content/uploads/2009/03/wpcms.jpg" alt="" title="wpcms" width="305" height="380" class="alignright size-full wp-image-1829" />I recently had a crash course in WordPress when I had to build a very custom website from scratch in two weeks from start to finish.   It needed to be WordPress because this site will contain a blog that will be handed off to a third party to maintain, and WordPress is arguably the industry standards for blogging software.  I wasn&#8217;t overly familiar with WordPress, I&#8217;d setup a blog or two in my time, but never anything as complex as building a custom theme or plugin.  But I basically knew everything I needed to do was possible, I&#8217;d read up on being able to create custom themes and plugins and I felt quite confident that I could get done everything I needed to.  What I didn&#8217;t know really was how I was going to do it, or how it was going to run as a CMS once launched.  In the end I was surprised at how easy some things were to implement, and frustrated at the lack of what I would consider common tools.</p>
<p>What I realized pretty quickly were two things:-
<ol>
<li>The Administration Panel is kick-ass, it&#8217;s beautiful to look at and use and takes care of all the administration dirty work you&#8217;d have to do if you were writing from scratch.</li>
<li>I pretty much hate the core WordPress PHP code, no disrespect to the people that dedicated so much time to it over the years, but to me and for my purposes it&#8217;s a cluster-fuck of a headache.</li>
</ol>
<p>Look I&#8217;m not saying I&#8217;m right in this approach, but I&#8217;m pretty sure that this approach is right for me.  I follow a school of thought which basically says that if you can&#8217;t figure it out in less than an hour it&#8217;s broken (something I took away from a mesmerizing Rasmus Lerdorf keynote speech at a conference many years ago).  And that&#8217;s how I felt about much of the &#8220;automagic&#8221; internals of WordPress, I couldn&#8217;t figure them out for shit and I got more and more frustrated as I started to realize that I could be writing this myself from scratch, not just in a clean manner that I would obviously intimately understand, but also in less time that it is taking me to figure out the spaghetti code.  I felt the same way with the plugins, that by the time I&#8217;d searched through the thousands of plugins and actually found the one that does what I need, and installed it and played around with it, only to find that it doesn&#8217;t do exactly what I need at which point I&#8217;d have to jump back into the pool of plugins looking for another suitor. Even if I did eventually find exactly what I needed, which lets face it is rarely the case, I could have already written a more suitable and stable plugin myself.</p>
<p>But on the other hand the administration panel WordPress has to offer is truly something of beauty.  It takes care of all the user security, roles and permissions, pages and posts with vanity URLs, WYSIWYG editors, media uploads, and comment moderating, just to mention a few of it&#8217;s highlights.  Basically all the rudimentary crud we have to worry about when building a CMS from scratch, shit in my line of work the admin panel is often more complex than the front-end.  And not only is it solid in it&#8217;s task, so that you can feel comfortable that it&#8217;ll do its job without having to peek under the hood, but it has some sprinkles of scriptaculous and ajax so it also does it sexy.  And couple that with the fact that it&#8217;s extremely easy to implement your own custom menu items and modules to the panel makes for a great application.</p>
<p>So I basically ended up writing my own front-end.  I got familar with WordPress and found all the functions I needed to pull in the information I was generating with the admin panel.  I&#8217;d like to write about how you can get setup up with all the basics you need to get up to speed with where I am at with all of this. I&#8217;ll hopefully accomplish this by exploring the following topics over a number of entries:-
<ul>
<li>Create your own theme</li>
<li>Custom homepage</li>
<li>Making plugins</li>
<li>Understanding pages</li>
<li>Meta tags and custom fields</li>
<li>Custom RSS file</li>
</ul>
<p>By the way the WordPress site I built is <a href="http://www.thefordstory.com/" target=_new>www.thefordstory.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pixelsfromtheedge.com/2009/03/using-wordpress-as-custom-cms/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

