<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
 
    <title>Ennui Design</title>
    <link>http://ennuidesign.com</link>
    <description>
      Ennui Design is an independent web design and development effort by 23-year-old Jason Lengstorf.
      His blog discusses PHP, MySQL, JavaScript, XHTML, and CSS. And, sometimes, other stuff.
    </description>
    <language>en-us</language>

    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/EnnuiDesign" type="application/rss+xml" /><feedburner:emailServiceId>EnnuiDesign</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Win a Copy of PHP for Absolute Beginners!</title>
      <description>&lt;p&gt;For anyone who might be interested in getting their hands on a copy of &lt;a href="http://www.amazon.com/gp/product/1430224738?ie=UTF8&amp;amp;tag=ennudesi-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1430224738"&gt;&lt;em&gt;PHP for Absolute Beginners&lt;/em&gt;&lt;/a&gt;, there's a giveaway going on over at &lt;a href="http://brenelz.com/2009/11/02/giveaways-galore-as-brenelz-com-is-re-launched/"&gt;Brenelz Web Development&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Three copies are available, so &lt;a href="http://brenelz.com/2009/11/02/giveaways-galore-as-brenelz-com-is-re-launched/"&gt;head over to the site and get contest details&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;And I know I've been neglecting my blog. However, I'm working on an eight-part series with Chris Coyier right now that should kick off very soon, which covers the development of a PHP/AJAX application from concept to completion. Sorry for the delay, but this series should make up for it.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;A big thank you to anyone who has already &lt;a href="http://www.amazon.com/gp/product/1430224738?ie=UTF8&amp;amp;tag=ennudesi-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1430224738"&gt;purchased my book&lt;/a&gt;! If you've read it and have a minute, I (and my publishers) would really appreciate you taking a moment to &lt;a href="http://www.amazon.com/review/create-review/ref=cm_cr_dp_wr_but_bottom?ie=UTF8&amp;amp;nodeID=283155&amp;amp;asin=1430224738&amp;amp;store=books"&gt;review it on Amazon&lt;/a&gt;. Thank you again!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/Win+a+Copy+of+PHP+for+Absolute+Beginners%21"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/J24DovA_J71kpcH9K0u9gyrnYQg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J24DovA_J71kpcH9K0u9gyrnYQg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/J24DovA_J71kpcH9K0u9gyrnYQg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/J24DovA_J71kpcH9K0u9gyrnYQg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/FBvmvcDYNNc" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/FBvmvcDYNNc/Win+a+Copy+of+PHP+for+Absolute+Beginners%21</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/Win+a+Copy+of+PHP+for+Absolute+Beginners%21</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/Win+a+Copy+of+PHP+for+Absolute+Beginners%21</feedburner:origLink></item>
    <item>
      <title>Natural Sorting in MySQL</title>
      <description>&lt;h2&gt;Working Around MySQL's Lack of Built-In Support for Natural Sorting&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Several times in the last few projects I've built, I've come across the need to sort alphanumeric rows in a database by number (i.e. entry1, entry2, entry3, etc.). If you've ever tried to do this, you know that sorting entries that are alphanumeric is a pain.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;The Data&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;For our purposes, we'll be using the following table:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;Table: sorting_test&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| alphanumeric VARCHAR(75) | integer INT |&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| test1                    | 1           |&lt;br /&gt;
| test2                    | 2           |&lt;br /&gt;
| test3                    | 3           |&lt;br /&gt;
| test4                    | 4           |&lt;br /&gt;
| test5                    | 5           |&lt;br /&gt;
| test6                    | 6           |&lt;br /&gt;
| test7                    | 7           |&lt;br /&gt;
| test8                    | 8           |&lt;br /&gt;
| test9                    | 9           |&lt;br /&gt;
| test10                   | 10          |&lt;br /&gt;
| test11                   | 11          |&lt;br /&gt;
| test12                   | 12          |&lt;br /&gt;
+--------------------------+-------------+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Sorting by the column &lt;tt&gt;integer&lt;/tt&gt;, of course, presents no problems.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;Query: SELECT alphanumeric, integer&lt;br /&gt;
       FROM sorting_test&lt;br /&gt;
       ORDER BY integer&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| alphanumeric VARCHAR(75) | integer INT |&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| test1                    | 1           |&lt;br /&gt;
| test2                    | 2           |&lt;br /&gt;
| test3                    | 3           |&lt;br /&gt;
| test4                    | 4           |&lt;br /&gt;
| test5                    | 5           |&lt;br /&gt;
| test6                    | 6           |&lt;br /&gt;
| test7                    | 7           |&lt;br /&gt;
| test8                    | 8           |&lt;br /&gt;
| test9                    | 9           |&lt;br /&gt;
| test10                   | 10          |&lt;br /&gt;
| test11                   | 11          |&lt;br /&gt;
| test12                   | 12          |&lt;br /&gt;
+--------------------------+-------------+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;However, when we try sorting by the &lt;tt&gt;alphanumeric&lt;/tt&gt; column, we get unexpected results:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;Query: SELECT alphanumeric, integer&lt;br /&gt;
       FROM sorting_test&lt;br /&gt;
       ORDER BY alphanumeric&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| alphanumeric VARCHAR(75) | integer INT |&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| test1                    | 1           |&lt;br /&gt;
| test10                   | 10          |&lt;br /&gt;
| test11                   | 11          |&lt;br /&gt;
| test12                   | 12          |&lt;br /&gt;
| test2                    | 2           |&lt;br /&gt;
| test3                    | 3           |&lt;br /&gt;
| test4                    | 4           |&lt;br /&gt;
| test5                    | 5           |&lt;br /&gt;
| test6                    | 6           |&lt;br /&gt;
| test7                    | 7           |&lt;br /&gt;
| test8                    | 8           |&lt;br /&gt;
| test9                    | 9           |&lt;br /&gt;
+--------------------------+-------------+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Obviously, this is not the desired outcome. Since we're sorting alphabetically, the entries are actually in the correct order, but we need to find a way to sort numerically.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;There are a whole lot of solutions out there if you hit up Google for "&lt;a href="http://www.google.com/search?q=natural+sorting+in+mysql"&gt;natural sorting in MySQL&lt;/a&gt;." The one I've found to be the most straightforward is to sort by length first, then the column value.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;Query: SELECT alphanumeric, integer&lt;br /&gt;
       FROM sorting_test&lt;br /&gt;
       ORDER BY LENGTH(alphanumeric), alphanumeric&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| alphanumeric VARCHAR(75) | integer INT |&lt;br /&gt;
+--------------------------+-------------+&lt;br /&gt;
| test1                    | 1           |&lt;br /&gt;
| test2                    | 2           |&lt;br /&gt;
| test3                    | 3           |&lt;br /&gt;
| test4                    | 4           |&lt;br /&gt;
| test5                    | 5           |&lt;br /&gt;
| test6                    | 6           |&lt;br /&gt;
| test7                    | 7           |&lt;br /&gt;
| test8                    | 8           |&lt;br /&gt;
| test9                    | 9           |&lt;br /&gt;
| test10                   | 10          |&lt;br /&gt;
| test11                   | 11          |&lt;br /&gt;
| test12                   | 12          |&lt;br /&gt;
+--------------------------+-------------+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This works because the first nine entries are 5 characters long, with the tenth, eleventh, and twelfth entries at 6 characters; this creates two groups of entries that are then sub-sorted, resulting in our desired order.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This is a quick tip, but a useful one. Do you have a better way of forcing natural sorting in MySQL? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/Natural+Sorting+in+MySQL"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FpfYlh7arf0DKT9nuM6R9mvhO4s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FpfYlh7arf0DKT9nuM6R9mvhO4s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FpfYlh7arf0DKT9nuM6R9mvhO4s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FpfYlh7arf0DKT9nuM6R9mvhO4s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/oCn9kzji93M" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/oCn9kzji93M/Natural+Sorting+in+MySQL</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/Natural+Sorting+in+MySQL</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/Natural+Sorting+in+MySQL</feedburner:origLink></item>
    <item>
      <title>SXSW 2010, PHP for Absolute Beginners, and an Apology</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1250723224_33449.jpg" alt="Help get my panel included in SXSW 2010!" /&gt;&lt;br /&gt;&lt;p&gt;I know I've been silent on here for far too long, but I wouldn't have done it without good reason. Here's what I've been up to over the last two months!&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;&lt;em&gt;PHP for Absolute Beginners&lt;/em&gt;&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;At long last, I've finally finished my first book! It's called &lt;a href="http://bit.ly/xkXUI"&gt;&lt;em&gt;PHP for Absolute Beginners&lt;/em&gt;&lt;/a&gt;, and it should be on shelves in major booksellers next month sometime. It's already available for &lt;a href="http://bit.ly/xkXUI"&gt;preorder on Amazon&lt;/a&gt; (though you'll have to forgive the erroneous reference to PHP 6; I've been trying to get that removed for a couple months now), and I'd &lt;em&gt;really&lt;/em&gt; appreciate presales.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Despite the title touting the book as written "for absolute beginners," this book should have something for everybody. It covers the construction of a blog from scratch, including using .htaccess to create friendly URLs, resizing and resampling images with PHP's GD library, storing user comments with spam prevention and email validation using regex, and other goodies including using the &lt;a href="http://bit.ly"&gt;bit.ly&lt;/a&gt; API to generate short URLs for a "post to Twitter" link.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I'm really excited about this project, and I'm even more excited to hear your feedback!&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;SXSW 2010&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;I've also thrown my hat into the ring to do a &lt;a href="http://bit.ly/2IKoRg"&gt;presentation on AJAX&lt;/a&gt; at this year's SXSW Interactive Festival.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This presentation would be a joint effort between &lt;a href="http://twitter.com/robertbanh"&gt;Robert Banh&lt;/a&gt; and myself, and will cover REST and its role in modern web applications. We'll also go over JSON, who's using REST, and the rest of the basics of the technology.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This stuff is already really important in modern web design, and it's only going to become more relevant in days to come.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;In order to make this presentation a reality, I need your help! Please head over to the PanelPicker on the SXSW website and &lt;a href="http://bit.ly/2IKoRg"&gt;vote for my topic&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Finally, an Apology&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;I'm really sorry that I've been neglecting this blog, and it's a problem I intend to rectify starting next week.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I'll be back to posting articles on a semi-regular basis next week. In addition to posting on Ennui Design, I plan on submitting more articles to &lt;a href="http://bit.ly/uBCnq"&gt;NETTUTS&lt;/a&gt; and a few other great online publications.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Thanks for sticking with me, and I'll see you real soon!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/SXSW+2010%2C+PHP+for+Absolute+Beginners%2C+and+an+Apology"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TRfr57M3lJ1H0SDw8cb5HU4qFb0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TRfr57M3lJ1H0SDw8cb5HU4qFb0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TRfr57M3lJ1H0SDw8cb5HU4qFb0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TRfr57M3lJ1H0SDw8cb5HU4qFb0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/frSiKKSkD-M" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/frSiKKSkD-M/SXSW+2010%2C+PHP+for+Absolute+Beginners%2C+and+an+Apology</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/SXSW+2010%2C+PHP+for+Absolute+Beginners%2C+and+an+Apology</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/SXSW+2010%2C+PHP+for+Absolute+Beginners%2C+and+an+Apology</feedburner:origLink></item>
    <item>
      <title>JSON: What It Is, How It Works, and How to Use It</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1246555442_30455.jpg" alt="To Infinity and JSON!" /&gt;&lt;br /&gt;&lt;p&gt;My apologies for the lapse in posting; I'm in the midst of finishing my first book for &lt;a href="http://apress.com"&gt;Apress&lt;/a&gt; (it's called &lt;em&gt;PHP for  Absolute Beginners&lt;/em&gt;, and should be out later this year), and it's been  consuming most of my attention.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This week, however, I want to cover a topic that I feel has become an important  part of any developer's toolkit: the ability to load and manipulate JSON feeds  from other sites via AJAX.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Many sites are sharing data using JSON in addition to RSS feeds nowadays, and  with good reason: &lt;strong&gt;JSON feeds can be loaded asynchronously much more  easily than XML/RSS.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This article will cover the following:&lt;/p&gt;&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt; What is JSON? &lt;/li&gt;&lt;br /&gt;
&lt;li&gt; Why does JSON matter? &lt;/li&gt;&lt;br /&gt;
&lt;li&gt; How do we load JSON into a project? &lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;p&gt;We'll also use our newfound skills with JSON at the end of this project to  &lt;strong&gt;build a quick app that loads photos from Flickr without requiring a page  refresh.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/reading-json"&gt;See the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_reading-json.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;What Is JSON?&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt; is short for  &lt;strong&gt;JavaScript Object Notation&lt;/strong&gt;, and is &lt;em&gt;a way to store information  in an organized, easy-to-access manner.&lt;/em&gt; In a nutshell, it gives us a  human-readable collection of data that we can access in a really logical manner.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Storing JSON Data&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;As a simple example, information about me might be written in JSON as follows:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;var jason = {&lt;br /&gt;
	"age" : "24",&lt;br /&gt;
	"hometown" : "Missoula, MT",&lt;br /&gt;
	"gender" : "male"&lt;br /&gt;
};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This creates an object that we access using the variable &lt;tt&gt;jason&lt;/tt&gt;. By  enclosing the variable's value in curly braces, we're indicating that the value  is an object. Inside the object, we can declare any number of properties using  a &lt;tt&gt;"property-name" : "property-value"&lt;/tt&gt; pairing, separated by commas.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To access the information stored in &lt;tt&gt;jason&lt;/tt&gt;, we can &lt;strong&gt;simply refer to the  name of the property we need.&lt;/strong&gt; For instance, to access information about me, we  could use the following snippets:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;document.write('Jason is '+jason.age); // Output: Jason is 24&lt;br /&gt;
document.write('Jason is a '+jason.gender); // Output: Jason is a male&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Storing JSON Data in Arrays&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;A slightly more complicated example involves storing two people in one variable. To do this, we &lt;strong&gt;enclose multiple objects in square brackets,&lt;/strong&gt; which signifies an  array.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;For instance, if I needed to include information about myself and my brother in  one variable, I might use the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;var family = [{&lt;br /&gt;
	"name" : "Jason",&lt;br /&gt;
	"age" : "24",&lt;br /&gt;
	"gender" : "male"&lt;br /&gt;
},&lt;br /&gt;
{&lt;br /&gt;
	"name" : "Kyle",&lt;br /&gt;
	"age" : "21",&lt;br /&gt;
	"gender" : "male"&lt;br /&gt;
}];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To access this information, we need to access the array index of the person we  wish to access. For example, we would use the  following snippet to access info stored in &lt;tt&gt;family&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;document.write(family[1].name); // Output: Kyle&lt;br /&gt;
document.write(family[0].age); // Output: 24&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This is beneficial if it will be necessary to loop through stored information,  as it lends itself to a &lt;tt&gt;for&lt;/tt&gt; loop with an automatically incrementing  value.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Nesting JSON Data&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Another way to store multiple people in our variable would be to &lt;strong&gt;nest objects.&lt;/strong&gt; To do this, we would create something similar to the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;var family = {&lt;br /&gt;
	"jason" : {&lt;br /&gt;
		"name" : "Jason Lengstorf",&lt;br /&gt;
		"age" : "24",&lt;br /&gt;
		"gender" : "male"&lt;br /&gt;
	},&lt;br /&gt;
	"kyle" : {&lt;br /&gt;
		"name" : "Kyle Lengstorf",&lt;br /&gt;
		"age" : "21",&lt;br /&gt;
		"gender" : "male"&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Accessing information in nested objects is a little easier to understand; to  access information in the object, we would use the following snippet:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;document.write(family.jason.name); // Output: Jason Lengstorf&lt;br /&gt;
document.write(family.kyle.age); // Output: 21&lt;br /&gt;
document.write(family.jason.gender); // Output: male&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Nested JSON and arrays can be combined as needed to store as much data as necessary.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Why Does JSON Matter?&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;With the rise of  &lt;a href="http://en.wikipedia.org/wiki/Ajax_(programming)"&gt;AJAX&lt;/a&gt;-powered  sites, it's becoming more and more important for sites to be able to load data &lt;strong&gt;quickly  and &lt;em&gt;asynchronously&lt;/em&gt;,&lt;/strong&gt; or in the background without delaying page  rendering.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Switching up the contents of a certain element within our layouts  without requiring a page refresh adds a "wow" factor to our applications, not  to mention the added convenience for our users.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Because of the popularity and ease of social media, many sites rely on the  content provided by sites such as Twitter, Flickr, and others. These sites  provide RSS feeds, which are easy to import and use on the server-side, but if  we try to load them with AJAX, we run into a wall: &lt;strong&gt;&lt;em&gt;we can only load  an RSS feed if we're requesting it from the same domain it's hosted on.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;An attempt to load my Flickr account's RSS feed via jQuery's  &lt;a href="http://docs.jquery.com/Ajax/jQuery.ajax"&gt;&lt;tt&gt;$.ajax()&lt;/tt&gt;&lt;/a&gt; method  results in the following JavaScript error:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;[Exception... "Access to restricted URI denied" code: "1012" &lt;br /&gt;
nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" &lt;br /&gt;
location: "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js Line: 19"]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;JSON allows us to overcome the cross-domain issue because &lt;strong&gt;we can use a method called  &lt;a href="http://remysharp.com/2007/10/08/what-is-jsonp/"&gt;JSONP&lt;/a&gt; that uses a callback function to send the JSON data back to our domain.&lt;/strong&gt; It's this capability that makes JSON  so incredibly useful, as it opens up a lot of doors that were previously  difficult to work around.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;How Do We Load JSON into a Project?&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;One of the easiest ways to load JSON data into our web applications is to &lt;strong&gt;use  the &lt;a href="http://docs.jquery.com/Ajax/jQuery.ajax"&gt;&lt;tt&gt;$.ajax()&lt;/tt&gt;&lt;/a&gt; method available in the jQuery library.&lt;/strong&gt; The ease of  retrieving data will vary based on the site providing the data, but a simple  example might look like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;$.ajax(&lt;br /&gt;
	type:'GET',&lt;br /&gt;
	url:"http://example.com/users/feeds/",&lt;br /&gt;
	data:"format=json&amp;amp;id=123",&lt;br /&gt;
	success:function(feed) {&lt;br /&gt;
		document.write(feed);&lt;br /&gt;
	},&lt;br /&gt;
	dataType:'jsonp'&lt;br /&gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This example would request the latest feed items in JSON format and output them  to the browser. Obviously, we wouldn't want to output raw JSON data to the  browser, but this example shows the basics of loading JSON from an external  source.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;A Practical Example: Loading Flickr Streams with JSON and jQuery&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/reading-json"&gt;See the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_reading-json.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To show how JSON works in a real-world example, let's &lt;strong&gt;load photos from Flickr  using jQuery and the JSON version of Flickr's "Latest" photo feed.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Step 1: Create the AJAX Request&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Flickr's photostream feeds are relatively easy to access. All users have a  unique ID number, which we will send as part of the request to this URL.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;http://api.flickr.com/services/feeds/photos_public.gne&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The request we need to send asks for the latest photos from the user in  question, along with flags asking for a JSON-formatted response. The request we  need to send will look like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;id=&lt;strong&gt;XXXXXXXX@NXX&lt;/strong&gt;&amp;amp;lang=en-us&amp;amp;format=json&amp;amp;jsoncallback=?&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;In the above example, &lt;strong&gt;XXXXXXXX@NXX&lt;/strong&gt; needs to be replaced with  the user's ID.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We'll be writing a function, so the user's ID will be passed as an argument called &lt;tt&gt;flickrID&lt;/tt&gt;. Our function will be called &lt;tt&gt;loadFlickr()&lt;/tt&gt;.  Let's create the function that will load our JSON response:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;function loadFlickr(flickrid)&lt;br /&gt;
{&lt;br /&gt;
	$('#feed').html('&amp;lt;span&amp;gt;&amp;lt;img src="images/lightbox-ico-loading.gif" /&amp;gt;&amp;lt;/span&amp;gt;');&lt;br /&gt;
	$.ajax({&lt;br /&gt;
		type:'GET',&lt;br /&gt;
		url:"http://api.flickr.com/services/feeds/photos_public.gne",&lt;br /&gt;
		data:"id="+flickrid+"&amp;amp;lang=en-us&amp;amp;format=json&amp;amp;jsoncallback=?",&lt;br /&gt;
		success:function(feed) {&lt;br /&gt;
			// Do something with the response&lt;br /&gt;
		},&lt;br /&gt;
		dataType:'jsonp'&lt;br /&gt;
	});&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The returned JSON data will look something like this (note that I've removed  all but one of the returned photos for the sake of brevity):&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;({&lt;br /&gt;
	"title": "Uploads from ennuidesign",&lt;br /&gt;
	"link": "http://www.flickr.com/photos/ennuidesign/",&lt;br /&gt;
	"description": "",&lt;br /&gt;
	"modified": "2009-03-17T03:53:36Z",&lt;br /&gt;
	"generator": "http://www.flickr.com/",&lt;br /&gt;
	"items": [&lt;br /&gt;
	{&lt;br /&gt;
		"title": "This Is How You Get People to Talk About You",&lt;br /&gt;
		"link": "http://www.flickr.com/photos/ennuidesign/3361269251/",&lt;br /&gt;
		"media": {"m":"http://farm4.static.flickr.com/3470/3361269251_9c55e6dc24_m.jpg"},&lt;br /&gt;
		"date_taken": "2009-03-16T21:53:36-08:00",&lt;br /&gt;
		"description": "&amp;lt;p&amp;gt;&amp;lt;a href="http://www.flickr.com/people/ennuidesign/"&amp;gt;ennuidesign&amp;lt;/a&amp;gt; posted a photo:&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;&amp;lt;a href="http://www.flickr.com/photos/ennuidesign/3361269251/" title="This Is How You Get People to Talk About You"&amp;gt;&amp;lt;img src="http://farm4.static.flickr.com/3470/3361269251_9c55e6dc24_m.jpg" width="240" height="180" alt="This Is How You Get People to Talk About You" /&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;A guy I know, Trevor Gnauck, made this custom pint glass for me. He runs a company called &amp;lt;a href="http://www.bluedragonllc.com/"&amp;gt;Blue Dragon Custom Laser Engraving&amp;lt;/a&amp;gt; with his family, and he had no reason whatsoever to do anything nice for me.&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt; He did, though, and look how cool that is! I can now drink a beer out of my own likeness.&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt; I know it wasn't his intention, but this is how you get people to talk about you. Unprovoked kindness will always inspire kindness in return, and the power of a kind gesture should never be overlooked.&amp;lt;/p&amp;gt;",&lt;br /&gt;
		"published": "2009-03-17T03:53:36Z",&lt;br /&gt;
		"author": "nobody@flickr.com (ennuidesign)",&lt;br /&gt;
		"author_id": "29080075@N02",&lt;br /&gt;
		"tags": "gift ennuidesign trevorgnauck bluedragoncustomlaserengraving"&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// The rest of the photo entries go here...&lt;br /&gt;
&lt;br /&gt;
	]&lt;br /&gt;
})&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Step 2: Process the JSON Data&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;What we're going to do is &lt;strong&gt;display the thumbnails of the latest 16 photos, which  will link to the medium-sized display of the image.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The Flickr JSON is a little confusing, and it doesn't provide a direct link to  the thumbnail version of our photos, so we'll have to use some trickery on our  end to get to it, which we'll cover in just a moment.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Each photo entry is stored in an array called &lt;tt&gt;items&lt;/tt&gt;, which we access  in our AJAX call using &lt;tt&gt;feed.items&lt;/tt&gt;. To get to the data about each  entry, we'll loop through the items until we've either hit the last available  photo or 16 total photos; whichever comes first.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Let's modify our function and set up the loop:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;function loadFlickr(flickrid)&lt;br /&gt;
{&lt;br /&gt;
	// Display a loading icon in our display element&lt;br /&gt;
	$('#feed').html('&amp;lt;span&amp;gt;&amp;lt;img src="images/lightbox-ico-loading.gif" /&amp;gt;&amp;lt;/span&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
	// Request the JSON and process it&lt;br /&gt;
	$.ajax({&lt;br /&gt;
		type:'GET',&lt;br /&gt;
		url:"http://api.flickr.com/services/feeds/photos_public.gne",&lt;br /&gt;
		data:"id="+flickrid+"&amp;amp;lang=en-us&amp;amp;format=json&amp;amp;jsoncallback=?",&lt;br /&gt;
		success:function(feed) {&lt;br /&gt;
			// Create an empty array to store images&lt;br /&gt;
			var thumbs = [];&lt;br /&gt;
&lt;br /&gt;
			// Loop through the items&lt;br /&gt;
			for(var i=0, l=feed.items.length; i &amp;lt; l &amp;amp;&amp;amp; i &amp;lt; 16; ++i) &lt;br /&gt;
			{&lt;br /&gt;
				// Process each image&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// Display the thumbnails on the page&lt;br /&gt;
		},&lt;br /&gt;
		dataType:'jsonp'&lt;br /&gt;
	});&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The element we're interested in is the "m" element stored within the "media"  element. This can be accessed within our loop using &lt;tt&gt;feed.items[i].media.m&lt;/tt&gt;. &lt;strong&gt;We're going to run a regular expression on this value to get both the medium and  thumbnail image paths, which we'll assemble into a linked thumbnail image.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Then, we'll push the newly assembled HTML into the array of thumbs we created. After we've finished the loop, we'll &lt;strong&gt;combine all the images into one string of HTML&lt;/strong&gt; and replace the contents of our display element with the loaded thumbnails.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Let's add this functionality to our script:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;function loadFlickr(flickrid)&lt;br /&gt;
{&lt;br /&gt;
	// Display a loading icon in our display element&lt;br /&gt;
	$('#feed').html('&amp;lt;span&amp;gt;&amp;lt;img src="images/lightbox-ico-loading.gif" /&amp;gt;&amp;lt;/span&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
	// Request the JSON and process it&lt;br /&gt;
	$.ajax({&lt;br /&gt;
		type:'GET',&lt;br /&gt;
		url:"http://api.flickr.com/services/feeds/photos_public.gne",&lt;br /&gt;
		data:"id="+flickrid+"&amp;amp;lang=en-us&amp;amp;format=json&amp;amp;jsoncallback=?",&lt;br /&gt;
		success:function(feed) {&lt;br /&gt;
			// Create an empty array to store images&lt;br /&gt;
			var thumbs = [];&lt;br /&gt;
&lt;br /&gt;
			// Loop through the items&lt;br /&gt;
			for(var i=0, l=feed.items.length; i &amp;lt; l &amp;amp;&amp;amp; i &amp;lt; 16; ++i) &lt;br /&gt;
			{&lt;br /&gt;
				// Manipulate the image to get thumb and medium sizes&lt;br /&gt;
				var img = feed.items[i].media.m.replace(&lt;br /&gt;
					/^(.*?)_m.jpg$/, &lt;br /&gt;
					'&amp;lt;a href="$1.jpg"&amp;gt;&amp;lt;img src="$1_s.jpg" alt="" /&amp;gt;&amp;lt;/a&amp;gt;'&lt;br /&gt;
				);&lt;br /&gt;
&lt;br /&gt;
				// Add the new element to the array&lt;br /&gt;
				thumbs.push(img);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// Display the thumbnails on the page&lt;br /&gt;
			$('#feed').html(thumbs.join(''));&lt;br /&gt;
&lt;br /&gt;
			// A function to add a lightbox effect&lt;br /&gt;
			addLB();&lt;br /&gt;
		},&lt;br /&gt;
		dataType:'jsonp'&lt;br /&gt;
	});&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Note that I've also added a function called &lt;tt&gt;addLB()&lt;/tt&gt; to the end of this  function; this adds the  &lt;a href="http://leandrovieira.com/projects/jquery/lightbox/"&gt;lightbox&lt;/a&gt; effect to our thumbnails, which is purely for aesthetics.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Step 3: Call Our Function&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;At this point, we're ready to call our function. To load my Flickr stream, we  would need to call our function as follows:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="js"&gt;loadFlickr("29080075@N02");&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The example posted will pull multiple users' photostreams into the containing  box without causing a page refresh. Look at the source code on  &lt;a href="/demo/reading-json"&gt;the demo&lt;/a&gt; to see how it was done.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Keep in mind that this demo was to show how to load JSON data, and not on how  to implement the code to call the function. The JavaScript calls are inline,  which should NOT be used in a production script.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/reading-json"&gt;See the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_reading-json.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Have you used JSON before? Is there anything you'd like to clarify or see  further clarified about JSON? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/JSON%3A+What+It+Is%2C+How+It+Works%2C+and+How+to+Use+It"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nhGueIWSrhgS38ftV8mT71OwYHo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nhGueIWSrhgS38ftV8mT71OwYHo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nhGueIWSrhgS38ftV8mT71OwYHo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nhGueIWSrhgS38ftV8mT71OwYHo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/X7IOVZmnduU" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/X7IOVZmnduU/JSON%3A+What+It+Is%2C+How+It+Works%2C+and+How+to+Use+It</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/JSON%3A+What+It+Is%2C+How+It+Works%2C+and+How+to+Use+It</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/JSON%3A+What+It+Is%2C+How+It+Works%2C+and+How+to+Use+It</feedburner:origLink></item>
    <item>
      <title>Easily Create External Links Without the Target Attribute</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1245202052_66170.jpg" alt="Progressively enhance your sites to support external links" /&gt;&lt;br /&gt;&lt;p&gt;Today's tip is extremely short and simple, and to a lot of folks may be a  "Duh!" sort of tip, but I felt it was worth sharing.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I'm a big fan of &lt;strong&gt;keeping sites valid in XHTML 1.0 Strict.&lt;/strong&gt; When I first started  paying attention to standards, one of the things that stumped me right off the  bat was the use of external links.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;The Problem with &lt;tt&gt;target="_blank"&lt;/tt&gt;&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;As I'm sure most people know, &lt;strong&gt;the use of the &lt;tt&gt;target&lt;/tt&gt; attribute isn't  considered valid.&lt;/strong&gt; However, in order to open links in a new page, the only tool  provided by HTML is the &lt;tt&gt;target&lt;/tt&gt; attribute!&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I had been creating external links for as long as I could remember using the  following format:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;a href="http://example.com" target="_blank"&amp;gt;External link&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;The Fix: &lt;tt&gt;rel="external"&lt;/tt&gt;&lt;/h2&gt;&lt;br /&gt;
&lt;h3&gt;The HTML&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;When I started using &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;, I stumbled across  this little gem that allowed me to have my valid code &lt;em&gt;and&lt;/em&gt; external  links with one simple line of code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;a href="http://example.com" rel="external"&amp;gt;External link&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;The use of &lt;tt&gt;rel="external"&lt;/tt&gt; is perfectly valid,&lt;/strong&gt; and doesn't cause any  problems at all. However, this attribute won't work by itself. In order to  cause the links to open in a new page, we first need to employ a jQuery  one-liner.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The JavaScript&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;At the bottom of any page that features external links, we need to include one  line of jQuery code (and jQuery itself, of course):&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;
	$('a[rel="external"]').attr('target', '_blank');&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;And that's it. Seriously.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This method degrades gracefully: if the user doesn't have JavaScript, the link  will open in the same window. This method is easy, lightweight, and most  importantly, &lt;strong&gt;valid XHTML 1.0 Strict.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;Writing valid code should be high on any developer's to-do list,&lt;/strong&gt; and using the  &lt;tt&gt;rel="external"&lt;/tt&gt; trick is an easy way to take yourself one step closer  to completely valid sites.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Do you have any tricks to keep sites valid? How about a raw JavaScript,  MooTools, or other library method of doing the &lt;tt&gt;rel="external"&lt;/tt&gt; trick? Share it in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/Easily+Create+External+Links+Without+the+Target+Attribute"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MVOSGMrU9KSNco2mY0btKgbbsPc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MVOSGMrU9KSNco2mY0btKgbbsPc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MVOSGMrU9KSNco2mY0btKgbbsPc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MVOSGMrU9KSNco2mY0btKgbbsPc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/1zl3mUjVkLc" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/1zl3mUjVkLc/Easily+Create+External+Links+Without+the+Target+Attribute</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/Easily+Create+External+Links+Without+the+Target+Attribute</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/Easily+Create+External+Links+Without+the+Target+Attribute</feedburner:origLink></item>
    <item>
      <title>Show the Most Popular Categories with PHP</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1244611702_71801.jpg" alt="Array-handling tricks" /&gt;&lt;br /&gt;&lt;p&gt;This week, we'll be going over a quick way to determine what the most popular  tags are in a series of tagged entries.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Files and Data Required for This Exercise&lt;/h2&gt;&lt;br /&gt;
&lt;h3&gt;Files&lt;/h3&gt;&lt;br /&gt;
&lt;ol&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;popular_tags.php&lt;/tt&gt; &amp;mdash; This will contain the dummy code and the  function to process it&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h3&gt;Data&lt;/h3&gt;&lt;br /&gt;
&lt;ol&gt;&lt;br /&gt;
&lt;li&gt;Tags &amp;mdash; An array of comma-delimited strings containing tags&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Parsing Function &amp;mdash; Function to break apart the array and determine  which tags are the most popular&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h2&gt;The Tag Sets&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;For this exercise, we'll be using a comma-delimited string (i.e. "tag 1, tag 2,  tag 3, etc.") as a set, and we'll assume that there are multiple entries, each  with a set of tags generated by the user.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Pretty much every blog, bookmarking resource, and app these days features  tagging in some capacity. Tags help users quickly identify what an entry is  about, or what category an item belongs in.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Another benefit of using tags is that they allow us, as developers, to identify  trends in entries. By determining what tags occur most frequently, we can let  site visitors know what they're most likely to find within a blog or collection  of entries.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Dummy Tag Sets for This Exercise&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Normally, the tags would be stored in a database. However, for the sake of an  easy-to-understand exercise, we'll be using a plain array (the array will  function just like the result set returned from a database query). In our new   file for testing, called &lt;tt&gt;popular_tags.php&lt;/tt&gt;, add our array, which should  contain the following tag sets:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
$tag_array = array(&lt;br /&gt;
	'php, regular expressions, search',&lt;br /&gt;
	'php, arrays, javascript',&lt;br /&gt;
	'php, search, javascript',&lt;br /&gt;
	'php, arrays',&lt;br /&gt;
	'arrays, mysql'&lt;br /&gt;
);&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;These are tag sets that might exist on this blog. In this case, they're  separated by commas, but they could be separated by anything, really.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;The Parsing Function&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This function is simple, but it has to do a lot. Let's define the steps that  need to be followed by this function, which we'll call &lt;tt&gt;popularTags()&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;ol&gt;&lt;br /&gt;
&lt;li&gt;Accept the array of tag sets as an argument&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Create a new array that will contain the processed tag information&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Loop through each set of tags&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Break each tag set apart at the commas and remove extra whitespace before  and after the tags&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Loop through each separated tag individually&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Check if the current tag is already in the final array, and if so,  increment the value of that tag by one; if not, create the tag in the array  with a value of one&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Sort the array by occurrence, from highest to lowest, and return it&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h3&gt;Step 1: Accept the Array of Tag Sets&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To start, we need to declare our function and accept the array of tag sets as  an argument. In &lt;tt&gt;popular_tags.php&lt;/tt&gt;, let's add the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function popularTags($tag_array)&lt;br /&gt;
{&lt;br /&gt;
	// Process $tag_array&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Step 2: Create a New Array to Store Processed Tag Information&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To avoid a notice about undeclared variables, we need to instantiate the  variable that will contain the new array of processed tags. We'll call this  array &lt;tt&gt;$popular_tags&lt;/tt&gt;, and it will be initialized as an empty array.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This is going to be our return value. When finished we want this array to hold  each tag that occurred in the tag sets as an index, each containing a value  that represents how many times that tag occurred in the supplied array. For  example, if "tag1" occurs twice and "tag2" occurs once,  &lt;tt&gt;$popular_tags&lt;/tt&gt; would look like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
Array&lt;br /&gt;
(&lt;br /&gt;
    [tag1] =&amp;gt; 2&lt;br /&gt;
    [tag2] =&amp;gt; 1&lt;br /&gt;
)&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Update &lt;tt&gt;popularTags()&lt;/tt&gt; to contain the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&lt;br /&gt;
function popularTags($tag_array)&lt;br /&gt;
{&lt;br /&gt;
	// Instantiate the final tag array&lt;br /&gt;
	$popular_tags = array();&lt;br /&gt;
&lt;br /&gt;
	// Process $tag_array&lt;br /&gt;
&lt;br /&gt;
	return $popular_tags;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Steps 3 &amp;amp; 4: Loop Through Each Tag Set and Separate by Commas&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;With our function declared and accepting an array, and a new array instantiated  to contain our processed tags, we need to start processing the tags themselves.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To start, we need to access each tag set individually. The easiest way to do  this is to run a &lt;tt&gt;foreach&lt;/tt&gt; loop, giving us each element of the array  individually:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function popularTags($tag_array)&lt;br /&gt;
{&lt;br /&gt;
	// Instantiate the final tag array&lt;br /&gt;
	$popular_tags = array();&lt;br /&gt;
&lt;br /&gt;
	// Loop through each set of tags&lt;br /&gt;
	foreach($tag_array as $tags)&lt;br /&gt;
	{&lt;br /&gt;
		// Process each tag set&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Return the array&lt;br /&gt;
	return $popular_tags;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Next, we need to separate each tag set into an array of the tags contained  within it. Because we know the tag sets are comma delimited, we can use the  handy &lt;a href="http://php.net/explode"&gt;&lt;tt&gt;explode()&lt;/tt&gt;&lt;/a&gt; function to break  the string into an array, using the comma as the breaking point. Then, to make  sure all the extra leading and trailing whitespace is eliminated from each tag,  we use &lt;a href="http://php.net/array_map"&gt;&lt;tt&gt;array_map()&lt;/tt&gt;&lt;/a&gt; to call the  &lt;a href="http://php.net/trim"&gt;&lt;tt&gt;trim()&lt;/tt&gt;&lt;/a&gt; function on each element we  just created from the string.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We can do all of this in one line by inserting the following just inside our  loop:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function popularTags($tag_array)&lt;br /&gt;
{&lt;br /&gt;
	// Instantiate the final tag array&lt;br /&gt;
	$popular_tags = array();&lt;br /&gt;
&lt;br /&gt;
	// Loop through each set of tags&lt;br /&gt;
	foreach($tag_array as $tags)&lt;br /&gt;
	{&lt;br /&gt;
		/*&lt;br /&gt;
		 * Separate at the commas to get individual tags and&lt;br /&gt;
		 * trim the whitespace from each tag&lt;br /&gt;
		 */&lt;br /&gt;
		$tags_arr = array_map('trim', explode(',', $tags));&lt;br /&gt;
&lt;br /&gt;
		// Process the tags in $tags_arr&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Return the array&lt;br /&gt;
	return $popular_tags;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Steps 5 &amp;amp; 6: Loop Through Each Tag and Check Against the Final Array&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Now that we have each tag stored in an individual array element, we can start  checking which tags are the most popular. To do this, we're going to loop  through each tag in the &lt;tt&gt;$tags_arr&lt;/tt&gt; array. If the tag we're currently  dealing with has already been added to the &lt;tt&gt;$popular_tags&lt;/tt&gt; array, we  increment it's value by one (meaning the original occurrence of a tag sets the  array element for that tag to one, and each subsequent occurrence increments  that value, effectively giving us a tag count). Otherwise, we'll simply add a  new array element to the &lt;tt&gt;$popular_tags&lt;/tt&gt; array and set its value to 1.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function popularTags($tag_array)&lt;br /&gt;
{&lt;br /&gt;
	// Instantiate the final tag array&lt;br /&gt;
	$popular_tags = array();&lt;br /&gt;
&lt;br /&gt;
	// Loop through each set of tags&lt;br /&gt;
	foreach($tag_array as $tags)&lt;br /&gt;
	{&lt;br /&gt;
		/*&lt;br /&gt;
		 * Separate at the commas to get individual tags and&lt;br /&gt;
		 * trim the whitespace from each tag&lt;br /&gt;
		 */&lt;br /&gt;
		$tags_arr = array_map('trim', explode(',', $tags));&lt;br /&gt;
&lt;br /&gt;
		// Loop through each tag&lt;br /&gt;
		foreach($tags_arr as $tag)&lt;br /&gt;
		{&lt;br /&gt;
			/*&lt;br /&gt;
			 * If the tag has already been added to the&lt;br /&gt;
			 * $popular_tags array, increment its value by 1&lt;br /&gt;
			 */&lt;br /&gt;
			if(array_key_exists($tag, $popular_tags))&lt;br /&gt;
			{&lt;br /&gt;
				$popular_tags[$tag] += 1;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Otherwise, add the tag to the array and &lt;br /&gt;
			 * set its value to 1&lt;br /&gt;
			 */&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				$popular_tags[$tag] = 1;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Return the array&lt;br /&gt;
	return $popular_tags;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Step 7: Sort the Array and Return It&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Finally, we need to sort our array in descending order by occurrence, so that  the tags that occur most often are at the top, while the less popular tags are  at the bottom. There's a very handy array-handling function that does exactly  what we need called &lt;a href="http://php.net/arsort"&gt;&lt;tt&gt;arsort()&lt;/tt&gt;&lt;/a&gt;,  which means "array reverse sort".&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;It's worth noting that &lt;tt&gt;arsort()&lt;/tt&gt; does not return the sorted array.  Rather, it returns a boolean: &lt;tt&gt;TRUE&lt;/tt&gt; on success and &lt;tt&gt;FALSE&lt;/tt&gt; on  failure. Because of this, we cannot directly call  &lt;tt&gt;return arsort($popular_tags);&lt;/tt&gt;, as this would be output as 1 instead of  the expected array.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To sort our array, update &lt;tt&gt;popularTags()&lt;/tt&gt; by adding the call to  &lt;tt&gt;arsort()&lt;/tt&gt; just above the &lt;tt&gt;return&lt;/tt&gt; statement:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function popularTags($tag_array)&lt;br /&gt;
{&lt;br /&gt;
	// Instantiate the final tag array&lt;br /&gt;
	$popular_tags = array();&lt;br /&gt;
&lt;br /&gt;
	// Loop through each set of tags&lt;br /&gt;
	foreach($tag_array as $tags)&lt;br /&gt;
	{&lt;br /&gt;
		/*&lt;br /&gt;
		 * Separate at the commas to get individual tags and&lt;br /&gt;
		 * trim the whitespace from each tag&lt;br /&gt;
		 */&lt;br /&gt;
		$tags_arr = array_map('trim', explode(',', $tags));&lt;br /&gt;
&lt;br /&gt;
		// Loop through each tag&lt;br /&gt;
		foreach($tags_arr as $tag)&lt;br /&gt;
		{&lt;br /&gt;
			/*&lt;br /&gt;
			 * If the tag has already been added to the&lt;br /&gt;
			 * $popular_tags array, increment its value by 1&lt;br /&gt;
			 */&lt;br /&gt;
			if(array_key_exists($tag, $popular_tags))&lt;br /&gt;
			{&lt;br /&gt;
				$popular_tags[$tag] += 1;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Otherwise, add the tag to the array and &lt;br /&gt;
			 * set its value to 1&lt;br /&gt;
			 */&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				$popular_tags[$tag] = 1;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Sort the tags in the array in descending order&lt;br /&gt;
	arsort($popular_tags);&lt;br /&gt;
&lt;br /&gt;
	// Return the array&lt;br /&gt;
	return $popular_tags;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;The Output&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;First and foremost, when we display the results of &lt;tt&gt;popularTags()&lt;/tt&gt; when  the dummy tag sets are passed using  &lt;a href="http://php.net/print_r"&gt;&lt;tt&gt;print_r()&lt;/tt&gt;&lt;/a&gt;, we'll see the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
Array&lt;br /&gt;
(&lt;br /&gt;
    [php] =&amp;gt; 4&lt;br /&gt;
    [arrays] =&amp;gt; 3&lt;br /&gt;
    [javascript] =&amp;gt; 2&lt;br /&gt;
    [search] =&amp;gt; 2&lt;br /&gt;
    [mysql] =&amp;gt; 1&lt;br /&gt;
    [regular expressions] =&amp;gt; 1&lt;br /&gt;
)&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To use this information in a script, we might want to display each category  with its popularity in parentheses to give our users some idea of what the  entries on the site usually pertain to.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Add the following output script to &lt;tt&gt;popular_tags.php&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
foreach(popularTagsC($tag_array) as $tag=&amp;gt;$num)&lt;br /&gt;
{&lt;br /&gt;
	echo $tag, " (", $num, ")&amp;lt;br /&amp;gt;";&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To see the result, open the file in a browser. We should see the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
php (4)&lt;br /&gt;
arrays (3)&lt;br /&gt;
javascript (2)&lt;br /&gt;
search (2)&lt;br /&gt;
mysql (1)&lt;br /&gt;
regular expressions (1)&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;The Condensed Function&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;When the comments are removed and a couple of things are combined to save  space, we can take &lt;tt&gt;popularTags()&lt;/tt&gt; down to just 11 lines of code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function popularTags($tag_array) {&lt;br /&gt;
	$p = array();&lt;br /&gt;
	foreach($tag_array as $tags) {&lt;br /&gt;
		$tags_arr = array_map('trim', explode(',', $tags));&lt;br /&gt;
		foreach($tags_arr as $tag) {&lt;br /&gt;
			$p[$tag] = array_key_exists($tag, $p) ? $p[$tag]+1 : 1;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	arsort($p);&lt;br /&gt;
	return $p;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;In this exercise, we learned how to break strings apart into arrays in order  to determine the frequency with which certain tags or words are used.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Do you have a way to further compress this function? Let me know in the  comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/Show+the+Most+Popular+Categories+with+PHP"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D9B-KIb-91Dy30CYjlJ47CKMlRo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D9B-KIb-91Dy30CYjlJ47CKMlRo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D9B-KIb-91Dy30CYjlJ47CKMlRo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D9B-KIb-91Dy30CYjlJ47CKMlRo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/ZwAgOaA3Ab8" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/ZwAgOaA3Ab8/Show+the+Most+Popular+Categories+with+PHP</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/Show+the+Most+Popular+Categories+with+PHP</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/Show+the+Most+Popular+Categories+with+PHP</feedburner:origLink></item>
    <item>
      <title>Improving the Simple Contact Form</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1244009077_12395.jpg" alt="Adding Usability Improvements and Spam Protection" /&gt;&lt;br /&gt;&lt;p&gt;A few weeks back, we learned how to  &lt;a href="blog/ITT+%2315%3A+Create+a+Simple+Contact+Form"&gt;build a simple  contact form&lt;/a&gt; to allow our users to send us feedback directly from a site.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;As noted in the comments, there were a few shortcomings with the contact form.  Most notably, there was no spam protection whatsoever. Additionally, if the  user made a mistake, their message would be lost, which is extremely  inconvenient.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To make this contact form ready to use on a real website, we'll be adding both  a basic spam protection system and the ability to store the message in a  session in case the user makes a mistake.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Like all projects built on this blog, this is being  presented as a teaching exercise and a demonstration, so be sure to  double-check it before using it in a project.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/contact_form2"&gt;View the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_contact-form2.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Understanding the Problem, Part 1: Better Error Handling&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;One of the most annoying things our web form could do is allow us to spend  twenty minutes crafting a message, only to realize that we forgot to add the  ".com" to our email address and therefore had our information rejected by the  application and lost. (By the way, I know the comment form on this blog does  that. It's on my to-do list, I swear!)&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To save our users a lot of frustration, we'll need to update our contact form  to &lt;strong&gt;save the information entered&lt;/strong&gt; before checking for validity. This allows us to  return an error message to the user telling them what went wrong, &lt;em&gt;as well  as keeping their original message intact.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Understanding the Problem, Part 2: Spam Protection&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Because there's still that special kind of asshole that builds robots to find  and spam any available web form, we need to &lt;strong&gt;guard our form against automated  submissions.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The most popular method for deterring robots is to use  &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Captcha"&gt;CAPTCHA&lt;/a&gt;&lt;/em&gt;, or a type  of challenge-response test that essentially proves that a user is human. This  form of spam protection is really effective, but can also have the unwanted  side-effect of protecting your form against people as well, since the warped  letters can be hard to read.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;All that a CAPTCHA does, though, is gives the user an instruction (such as,  "Type the letters from the image below") and checks their response. Because  our form is not granting access to sensitive data, we don't need to generate a  bulletproof spam protection service. Therefore, we're going to use a much  simpler approach: &lt;strong&gt;we're going to ask a basic arithmetic question and check the  answer. &lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Because it takes a relatively smart spambot to interpret a question, we're  going to trust that only a human will understand the question, "What is 4 + 5?"  If the user gives us the answer, 9, then we know with relative certainty that  the message is legitimate.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Solving the Problem&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;For this project, I'm going to assume that everyone's familiar with the  &lt;a href="blog/ITT+%2315%3A+Create+a+Simple+Contact+Form"&gt;original post&lt;/a&gt;.  All code will be presented, but the explanation for &lt;em&gt;how&lt;/em&gt; the code  works will be omitted. &lt;strong&gt;Refer to the original post for explanations on the  parts of the contact form not covered here. &lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This project consists of four files:&lt;/p&gt;&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;tt&gt;index.php&lt;/tt&gt;&lt;/strong&gt; &amp;mdash; contains our form and error  handling&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;tt&gt;contact.inc.php&lt;/tt&gt;&lt;/strong&gt; &amp;mdash; processes submitted messages and  returns a status message&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;tt&gt;default.css&lt;/tt&gt;&lt;/strong&gt; &amp;mdash; CSS styles for the form&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;tt&gt;beautiful-forms.js&lt;/tt&gt;&lt;/strong&gt; &amp;mdash; adds JavaScript form validation  and cleans up forms (read about it  &lt;a href="blog/Beautiful+Forms+with+JavaScript"&gt;here&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;h2&gt;Step 1 &amp;mdash; Adding Better Error Handling&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Originally, our error handling only involved outputting a basic message and  killing the execution of our script. Obviously, this isn't acceptable for a  real site, so we're going to improve it.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Saving the Submitted Information in Case of Errors&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;First and foremost, we want to&lt;strong&gt; remove the annoyance of needing to re-enter  information in the event of a mistake on the form.&lt;/strong&gt; To do this, we're going to  use session variables.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;In order to use sessions, we need to have a session available to us, which we  accomplish using &lt;tt&gt;session_start()&lt;/tt&gt; at the very top of any file that will  need access to the saved information. In this case, we'll need to add the call  to both &lt;tt&gt;index.php&lt;/tt&gt; and &lt;tt&gt;contact.inc.php&lt;/tt&gt; for our script to work.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Start the session&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;After we open the session, we &lt;strong&gt;remove the whitespace&lt;/strong&gt; from before and after the  form's submitted values using a really handy function called  &lt;a href="http://php.net/array_map"&gt;&lt;tt&gt;array_map()&lt;/tt&gt;&lt;/a&gt;, which allows us to  call a function on each element of an array. We're using it here to call the  &lt;a href="http://php.net/trim"&gt;&lt;tt&gt;trim()&lt;/tt&gt;&lt;/a&gt; function on all submitted  values in the &lt;tt&gt;$_POST&lt;/tt&gt; superglobal. The return value of  &lt;tt&gt;array_map()&lt;/tt&gt; will then be stored in a variable, which we'll simply call  &lt;tt&gt;$p&lt;/tt&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Start the session&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * If the form was submitted and the "Send" button pressed, &lt;br /&gt;
 * continue processing the data&lt;br /&gt;
 */&lt;br /&gt;
if($_SERVER['REQUEST_METHOD']=='POST' &amp;amp;&amp;amp; $_POST['submit']=='Send')&lt;br /&gt;
{&lt;br /&gt;
	// Trim all the values to remove unwanted whitespace&lt;br /&gt;
	$p = array_map('trim', $_POST);&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;With our values trimmed and stored, we're ready to &lt;strong&gt;save them in the session.&lt;/strong&gt; To do this, we simply create an array element in the &lt;tt&gt;$_SESSION&lt;/tt&gt; superglobal for each form field and set its value to the submitted information.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Start the session&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * If the form was submitted and the "Send" button pressed, &lt;br /&gt;
 * continue processing the data&lt;br /&gt;
 */&lt;br /&gt;
if($_SERVER['REQUEST_METHOD']=='POST' &amp;amp;&amp;amp; $_POST['submit']=='Send')&lt;br /&gt;
{&lt;br /&gt;
	// Trim all the values to remove unwanted whitespace&lt;br /&gt;
	$p = array_map('trim', $_POST);&lt;br /&gt;
&lt;br /&gt;
	// Store the posted information as session variables&lt;br /&gt;
	$_SESSION['cf_n'] = $p['cf_n'];&lt;br /&gt;
	$_SESSION['cf_e'] = $p['cf_e'];&lt;br /&gt;
	$_SESSION['cf_w'] = $p['cf_w'];&lt;br /&gt;
	$_SESSION['cf_h'] = $p['cf_h'];&lt;br /&gt;
	$_SESSION['cf_m'] = $p['cf_m'];&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;Now the submitted information is available to our script, even if the form  submission fails, &lt;/strong&gt;allowing us to grant our users another chance to get the form right without causing them much grief. We'll get to how this information is  used in just a moment.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Using Status Codes to Identify Errors&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Next we need to modify our error handling. In the original post, we simply  saved an error message in a variable, which was output to the browser using  &lt;tt&gt;echo()&lt;/tt&gt; in the event of an error. Our new approach is to &lt;strong&gt;catch an error  by sending the user back to the form with a status code that identifies it. &lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;For simplicity's sake, we're going to use the following status codes:&lt;/p&gt;&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;0&lt;/tt&gt; &amp;mdash; No error&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;1&lt;/tt&gt; &amp;mdash; Anti-spam question incorrect or incomplete&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;2&lt;/tt&gt; &amp;mdash; No name submitted&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;3&lt;/tt&gt; &amp;mdash; Invalid email submitted&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;4&lt;/tt&gt; &amp;mdash; No message submitted&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;5&lt;/tt&gt; &amp;mdash; Sending of message failed&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;6&lt;/tt&gt; &amp;mdash; Sending of confirmation message failed&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;p&gt;Each step in the validation process checks for an individual field's validity.  If the field does not meet our criteria for being considered "valid", we &lt;strong&gt;send  our status code for the error as a URL query string&lt;/strong&gt; and use  &lt;a href="http://php.net/header"&gt;&lt;tt&gt;header()&lt;/tt&gt;&lt;/a&gt; to direct the user back  to the form, where an error message will be displayed.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Modify &lt;tt&gt;contact.inc.php&lt;/tt&gt; to contain the following code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Start the session&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * If the form was submitted and the "Send" button pressed, &lt;br /&gt;
 * continue processing the data&lt;br /&gt;
 */&lt;br /&gt;
if($_SERVER['REQUEST_METHOD']=='POST' &amp;amp;&amp;amp; $_POST['submit']=='Send')&lt;br /&gt;
{&lt;br /&gt;
	// Trim all the values to remove unwanted whitespace&lt;br /&gt;
	$p = array_map('trim', $_POST);&lt;br /&gt;
&lt;br /&gt;
	// Store the posted information as session variables&lt;br /&gt;
	$_SESSION['cf_n'] = $p['cf_n'];&lt;br /&gt;
	$_SESSION['cf_e'] = $p['cf_e'];&lt;br /&gt;
	$_SESSION['cf_w'] = $p['cf_w'];&lt;br /&gt;
	$_SESSION['cf_h'] = $p['cf_h'];&lt;br /&gt;
	$_SESSION['cf_m'] = $p['cf_m'];&lt;br /&gt;
&lt;br /&gt;
	// If the name field was filled out, sanitize the input and store it&lt;br /&gt;
	if(!empty($p['cf_n']) &amp;amp;&amp;amp; $p['cf_n']!='Name (required)')&lt;br /&gt;
	{&lt;br /&gt;
		$name = htmlentities(stripslashes($p['cf_n']), ENT_QUOTES);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// If the name wasn't entered, create an error message&lt;br /&gt;
		header("Location: ../?status=2");&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If the email is set, validate and store it&lt;br /&gt;
	if(!empty($p['cf_e']) &amp;amp;&amp;amp; $p['cf_e']!='Email (required)')&lt;br /&gt;
	{&lt;br /&gt;
		// Define a regex pattern to validate the email address&lt;br /&gt;
		$pattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";&lt;br /&gt;
			if (preg_match($pattern, $p['cf_e']))&lt;br /&gt;
			{&lt;br /&gt;
				$email = $p['cf_e'];&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				// If the email doesn't match the pattern, error&lt;br /&gt;
				header("Location: ../?status=3");&lt;br /&gt;
				exit;&lt;br /&gt;
			}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If no email was entered, generate an error message&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		header("Location: ../?status=3");&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Check the website field&lt;br /&gt;
	if(!empty($p['cf_w']) &amp;amp;&amp;amp; $p['cf_w']!='Website (optional)')&lt;br /&gt;
	{&lt;br /&gt;
		$site = htmlentities(stripslashes($p['cf_w']), ENT_QUOTES);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// Because the website is optional, no error if empty&lt;br /&gt;
		$site = "none";&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Ensure a message was entered, then sanitize it&lt;br /&gt;
	if(!empty($p['cf_m']) &amp;amp;&amp;amp; $p['cf_m']!='Enter Your Message Here')&lt;br /&gt;
	{&lt;br /&gt;
		$message = strip_tags(stripslashes($p['cf_m']));&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If no message was entered, adds an error message&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		header("Location: ../?status=4");&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * If no errors occurred, send the message&lt;br /&gt;
	 */&lt;br /&gt;
	$to = "Ennui Design &amp;lt;answers@ennuidesign.com&amp;gt;";&lt;br /&gt;
	$subject = "[Ennui Design] Message from the Ennui Design contact form";&lt;br /&gt;
	$headers = &amp;lt;&amp;lt;&amp;lt;MESSAGE_HEADER&lt;br /&gt;
From: $name &amp;lt;$email&amp;gt;&lt;br /&gt;
Content-Type: text/plain&lt;br /&gt;
MESSAGE_HEADER;&lt;br /&gt;
	$msg = &amp;lt;&amp;lt;&amp;lt;MESSAGE_BODY&lt;br /&gt;
Name:  $name&lt;br /&gt;
Email: $email&lt;br /&gt;
URL:   $site&lt;br /&gt;
&lt;br /&gt;
Message:&lt;br /&gt;
&lt;br /&gt;
$message&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
This message was sent via the contact form on EnnuiDesign.com&lt;br /&gt;
MESSAGE_BODY;&lt;br /&gt;
	if(!mail($to, $subject, $msg, $headers))&lt;br /&gt;
	{&lt;br /&gt;
		header("Location: ../?status=5");&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Now send a confirmation email to the user.&lt;br /&gt;
	$conf_to  = "$name &amp;lt;$email&amp;gt;";&lt;br /&gt;
	$conf_sub = "Thank You for Contacting Us!";&lt;br /&gt;
	$conf_headers = &amp;lt;&amp;lt;&amp;lt;MESSAGE_HEADER&lt;br /&gt;
From: Ennui Design &amp;lt;donotreply@ennuidesign.com&amp;gt;&lt;br /&gt;
Content-Type: text/plain&lt;br /&gt;
MESSAGE_HEADER;&lt;br /&gt;
		$conf_message = &amp;lt;&amp;lt;&amp;lt;MESSAGE_BODY&lt;br /&gt;
Thank you for contacting us! Your message&lt;br /&gt;
was sent successfully, and we will get back&lt;br /&gt;
to you as quickly as possible.&lt;br /&gt;
&lt;br /&gt;
All the Best,&lt;br /&gt;
Ennui Design&lt;br /&gt;
&lt;br /&gt;
answers@ennuidesign.com&lt;br /&gt;
www.EnnuiDesign.com&lt;br /&gt;
MESSAGE_BODY;&lt;br /&gt;
	if(!mail($conf_to, $conf_sub, $conf_message, $conf_headers))&lt;br /&gt;
	{&lt;br /&gt;
		header("Location: ../?status=6");&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Destroy the session variables&lt;br /&gt;
	unset($_SESSION['cf_n'], $_SESSION['cf_e'], $_SESSION['cf_w'], $_SESSION['cf_h'], $_SESSION['cf_m']);&lt;br /&gt;
&lt;br /&gt;
	// Send the user back to the main page&lt;br /&gt;
	header('Location: ../?status=0');&lt;br /&gt;
	exit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
	 * If the wrong request method was used or the "Send" button&lt;br /&gt;
	 * wasn't pressed (i.e. "Cancel" was pressed), return the user&lt;br /&gt;
	 * to the contact form with no message.&lt;br /&gt;
	 */&lt;br /&gt;
	header("Location: ../");&lt;br /&gt;
	exit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Assigning Messages to Status Codes&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In &lt;tt&gt;index.php&lt;/tt&gt;, we're going to check if a status code was sent, then  &lt;strong&gt;use a switch to assign a message to each status code&lt;/strong&gt; we'll be creating.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Place the following code into &lt;tt&gt;index.php&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// If an error exists, generate a message to correspond&lt;br /&gt;
if(isset($_GET['status']))&lt;br /&gt;
{&lt;br /&gt;
	$class = NULL;&lt;br /&gt;
	switch($_GET['status'])&lt;br /&gt;
	{&lt;br /&gt;
		case 0:&lt;br /&gt;
			$class = ' class="success"';&lt;br /&gt;
			$error = "Your message was sent successfully!";&lt;br /&gt;
			break;&lt;br /&gt;
		case 1:&lt;br /&gt;
			$error = "Make sure you answer the anti-spam question before sending!";&lt;br /&gt;
			break;&lt;br /&gt;
		case 2:&lt;br /&gt;
			$error = "Please enter your name before sending!";&lt;br /&gt;
			break;&lt;br /&gt;
		case 3: &lt;br /&gt;
			$error = "Please enter a valid email address!";&lt;br /&gt;
			break;&lt;br /&gt;
		case 4:&lt;br /&gt;
			$error = "Please enter a message before sending!";&lt;br /&gt;
			break;&lt;br /&gt;
		case 5:&lt;br /&gt;
			$error = "Something went wrong while sending your message. Please try again!";&lt;br /&gt;
			break;&lt;br /&gt;
		case 6:&lt;br /&gt;
			$error = "Your message was sent, but the confirmation message failed. Sorry about that!";&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			$error = "Something unexpected happened. Please try again!";&lt;br /&gt;
			break;&lt;br /&gt;
	}&lt;br /&gt;
	$err_msg = "&amp;lt;h3$class&amp;gt;$error&amp;lt;/h3&amp;gt;";&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
	$err_msg = NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Note that in the event of status code &lt;tt&gt;0&lt;/tt&gt;, we add a class named "success" to the  &lt;tt&gt;&amp;lt;h3&amp;gt;&lt;/tt&gt; tag. &lt;em&gt;This is so that our success message doesn't get styled  to look like an error. &lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Using Saved Data to Repopulate Form Fields&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;If our form encountered an error, we want to &lt;strong&gt;place the previously submitted  information back into the appropriate fields,&lt;/strong&gt; as well as display the error  message we just stored in the variable &lt;tt&gt;$err_msg&lt;/tt&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To accomplish this, we need to access the session variables we created in  &lt;tt&gt;contact.inc.php&lt;/tt&gt;. At the very top of &lt;tt&gt;index.php&lt;/tt&gt;, before our  status code check, we're going to access the session with  &lt;tt&gt;session_start()&lt;/tt&gt;, then check if our field variables are set. If so,  we'll strip any slashes using  &lt;a href="http://php.net/stripslashes"&gt;&lt;tt&gt;stripslashes()&lt;/tt&gt;&lt;/a&gt; and &lt;strong&gt;store the  value as an easy-to-access variable&lt;/strong&gt; (i.e. &lt;tt&gt;$name&lt;/tt&gt; for the  &lt;tt&gt;$_SESSION['cf_n']&lt;/tt&gt; variable, &lt;tt&gt;$email&lt;/tt&gt; for the  &lt;tt&gt;$_SESSION['cf_e']&lt;/tt&gt; variable, etc.) for later use.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
// Load the saved session info if it exists&lt;br /&gt;
$name = (isset($_SESSION['cf_n'])) ? stripslashes($_SESSION['cf_n']) : NULL;&lt;br /&gt;
$email = (isset($_SESSION['cf_e'])) ? stripslashes($_SESSION['cf_e']) : NULL;&lt;br /&gt;
$web = (isset($_SESSION['cf_w'])) ? stripslashes($_SESSION['cf_w']) : NULL;&lt;br /&gt;
$human = (isset($_SESSION['cf_h'])) ? stripslashes($_SESSION['cf_h']) : NULL;&lt;br /&gt;
$msg = (isset($_SESSION['cf_m'])) ? stripslashes($_SESSION['cf_m']) : NULL;&lt;br /&gt;
&lt;br /&gt;
// If an error exists, generate a message to correspond&lt;br /&gt;
if(isset($_GET['status']))&lt;br /&gt;
{&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To display the saved information if it exists, we need to &lt;strong&gt;add &lt;tt&gt;value&lt;/tt&gt; attributes to our form fields.&lt;/strong&gt; In the HTML form within &lt;tt&gt;index.php&lt;/tt&gt;,  modify the code to contain the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
	&amp;lt;h1&amp;gt; Simple Contact Form &amp;lt;/h1&amp;gt;&lt;br /&gt;
	&amp;lt;?php echo $err_msg ?&amp;gt;&lt;br /&gt;
	&amp;lt;form action="inc/contact.inc.php" method="post" id="cf"&amp;gt;&lt;br /&gt;
		&amp;lt;fieldset&amp;gt;&lt;br /&gt;
			&amp;lt;legend&amp;gt;Send a Message&amp;lt;/legend&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_n"&amp;gt;Name (required)&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_n" name="cf_n" type="text" maxlength="75"&lt;br /&gt;
				value="&amp;lt;?php echo $name ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_e"&amp;gt;Email (required)&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_e" name="cf_e" type="text" maxlength="150"&lt;br /&gt;
				value="&amp;lt;?php echo $email ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_w"&amp;gt;Website (optional)&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_w" name="cf_w" type="text" maxlength="150"&lt;br /&gt;
				value="&amp;lt;?php echo $web ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_m"&amp;gt;Enter Your Message Here&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;textarea id="cf_m" name="cf_m"&lt;br /&gt;
				rows="14" cols="45"&amp;gt;&amp;lt;?php echo $msg ?&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;
			&amp;lt;input type="submit" name="submit" class="submit" value="Send" /&amp;gt;&lt;br /&gt;
			&amp;lt;input type="submit" name="submit" class="submit" value="Cancel" /&amp;gt;&lt;br /&gt;
		&amp;lt;/fieldset&amp;gt;&lt;br /&gt;
	&amp;lt;/form&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Now, if we load the form in a browser and enter an incorrect email address or  omit a field, we should be given an error message, and the form should still  contain the values we entered before submitting.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 2 &amp;mdash; Adding Spam Protection&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Our first step when adding spam protection is to create a field that will be  used to determine if a user is human (you may have noticed the variables  referring to &lt;tt&gt;$human&lt;/tt&gt; or &lt;tt&gt;$_POST['cf_h']&lt;/tt&gt; above).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Add the anti-spam field to our form in &lt;tt&gt;index.php&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
	&amp;lt;h1&amp;gt; Simple Contact Form &amp;lt;/h1&amp;gt;&lt;br /&gt;
	&amp;lt;?php echo $err_msg ?&amp;gt;&lt;br /&gt;
	&amp;lt;form action="inc/contact.inc.php" method="post" id="cf"&amp;gt;&lt;br /&gt;
		&amp;lt;fieldset&amp;gt;&lt;br /&gt;
			&amp;lt;legend&amp;gt;Send a Message&amp;lt;/legend&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_n"&amp;gt;Name (required)&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_n" name="cf_n" type="text" maxlength="75"&lt;br /&gt;
				value="&amp;lt;?php echo $name ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_e"&amp;gt;Email (required)&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_e" name="cf_e" type="text" maxlength="150"&lt;br /&gt;
				value="&amp;lt;?php echo $email ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_w"&amp;gt;Website (optional)&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_w" name="cf_w" type="text" maxlength="150"&lt;br /&gt;
				value="&amp;lt;?php echo $web ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_h"&amp;gt;Spam Check: What is 4 + 5?&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;input id="cf_h" name="cf_h" type="text" maxlength="4"&lt;br /&gt;
				value="&amp;lt;?php echo $human ?&amp;gt;" /&amp;gt;&lt;br /&gt;
			&amp;lt;p class="hint"&amp;gt;HINT: The answer is 9&amp;lt;/p&amp;gt;&lt;br /&gt;
			&amp;lt;label for="cf_m"&amp;gt;Enter Your Message Here&amp;lt;/label&amp;gt;&lt;br /&gt;
			&amp;lt;textarea id="cf_m" name="cf_m" rows="14" cols="45"&amp;gt;&amp;lt;?php echo $msg ?&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;
			&amp;lt;input type="submit" name="submit" class="submit" value="Send" /&amp;gt;&lt;br /&gt;
			&amp;lt;input type="submit" name="submit" class="submit" value="Cancel" /&amp;gt;&lt;br /&gt;
		&amp;lt;/fieldset&amp;gt;&lt;br /&gt;
	&amp;lt;/form&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Next, in &lt;tt&gt;contact.inc.php&lt;/tt&gt;, we need to &lt;strong&gt;verify that the user did, indeed,  answer "9" to the challenge question.&lt;/strong&gt; To do so, near the top of  &lt;tt&gt;contact.inc.php&lt;/tt&gt; just after we save the form information, we can simply  add one more check:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
	// Store the posted information as session variables&lt;br /&gt;
	$_SESSION['cf_n'] = $p['cf_n'];&lt;br /&gt;
	$_SESSION['cf_e'] = $p['cf_e'];&lt;br /&gt;
	$_SESSION['cf_w'] = $p['cf_w'];&lt;br /&gt;
	$_SESSION['cf_h'] = $p['cf_h'];&lt;br /&gt;
	$_SESSION['cf_m'] = $p['cf_m'];&lt;br /&gt;
&lt;br /&gt;
	// Make sure the spam protection didn't fail&lt;br /&gt;
	if($p['cf_h'] != '9' &amp;amp;&amp;amp; $p['cf_h'] != 'nine')&lt;br /&gt;
	{&lt;br /&gt;
		header("Location: ../?status=1");&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If the name field was filled out, sanitize the input and store it&lt;br /&gt;
	if(!empty($p['cf_n']) &amp;amp;&amp;amp; $p['cf_n']!='Name (required)')&lt;br /&gt;
	{&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Our check will allow for both the answer "9" and the answer "nine", because we  don't want to confuse anyone. If the form isn't filled out correctly, the user  is &lt;strong&gt;redirected to the form with a status code.&lt;/strong&gt; Otherwise, execution continues  normally.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Some spam-bots don't acknowledge the &lt;tt&gt;header()&lt;/tt&gt; command, so we use the  &lt;tt&gt;exit;&lt;/tt&gt; command just to be safe. In the event that a spam bot is using  our contact form, it will either dead-end when the script exits, or it will end  up back at the form with no idea that it failed.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This isn't bulletproof, but it works for a small site that just wants to avoid  a ton of junk mail.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/contact_form2"&gt;View the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_contact-form2.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This form will allow a user to contact you directly through your site. It also  provides usability enhancements to save the user time in the event they make a  mistake while submitting the form. Our anti-spam measures are pretty  low-impact, which makes it easy for a user to prove they are human, while  keeping most of the bots out.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Do you have a better way to prevent spam? Any ideas on bulletproofing this  script? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/Improving+the+Simple+Contact+Form"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZZx3MnTijXujG9y9ZbYb7zfTze0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZZx3MnTijXujG9y9ZbYb7zfTze0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZZx3MnTijXujG9y9ZbYb7zfTze0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZZx3MnTijXujG9y9ZbYb7zfTze0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/1LK-eQpFVdk" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/1LK-eQpFVdk/Improving+the+Simple+Contact+Form</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/Improving+the+Simple+Contact+Form</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/Improving+the+Simple+Contact+Form</feedburner:origLink></item>
    <item>
      <title>Send HTML and Plain Text Versions of Email</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1243393534_92620.jpg" alt="Who has two thumbs and is recycling artwork again? This guy." /&gt;&lt;br /&gt;&lt;p&gt;Recently, I've been dealing with sending email from applications an awful lot.  At first glance, sending a basic message from PHP is easy:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
	mail('test@example.com', 'Subject Line', 'A message!');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Sending complex messages with HTML formatting and/or attachments, however, can  be tricky. Today, we're going to cover sending HTML email to a user while still  including a plain text version for email clients that don't support HTML.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/multipart_email"&gt;See the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_multipart-email.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Part One: Understanding Email Structure&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Basic email structure is something like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;To: someone@example.com&lt;br /&gt;
Subject: Test Email&lt;br /&gt;
From: Test &amp;lt;testing@example.com&amp;gt;&lt;br /&gt;
MIME-Version: 1.0&lt;br /&gt;
Content-Type: multipart/alternative;&lt;br /&gt;
 boundary="==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx"&lt;br /&gt;
X-Nonspam: None&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx&lt;br /&gt;
Content-Type: text/plain; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit&lt;br /&gt;
&lt;br /&gt;
This Is a Plain Text Email&lt;br /&gt;
&lt;br /&gt;
This message has no HTML. http://w3schools.com&lt;br /&gt;
&lt;br /&gt;
--==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx&lt;br /&gt;
Content-Type: text/html; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;This Is an HTML Email&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This message is composed in &amp;lt;a href="http://w3schools.com"&amp;gt;HTML&amp;lt;/a&amp;gt;.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
--==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx--&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This looks a little daunting at first, but if we take it in chunks, it's pretty  easy to understand. An email with both a plain text and HTML version will have  the following three parts:&lt;/p&gt;&lt;br /&gt;
&lt;ol&gt;&lt;br /&gt;
&lt;li&gt;Headers&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Plain text version&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;HTML version&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;p&gt;That's all there is to it! These three sections are separated by a &lt;strong&gt;&lt;em&gt;boundary  string&lt;/em&gt;&lt;/strong&gt;, which is essentially a random string to identify each section of the  message.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To further our understanding, let's take each section one-by-one.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Headers&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Our first section in an email is the message headers.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;To: someone@example.com&lt;br /&gt;
Subject: Test Email&lt;br /&gt;
From: Test &amp;lt;testing@example.com&amp;gt;&lt;br /&gt;
MIME-Version: 1.0&lt;br /&gt;
Content-Type: multipart/alternative;&lt;br /&gt;
 boundary="==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx"&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The "To", "Subject", and "From" headers, separated by a line break, are pretty  straightforward: they determine who the message is to, what the subject is, and  who the message is from.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Next, we pass a &lt;a href="http://en.wikipedia.org/wiki/MIME"&gt;MIME-Type&lt;/a&gt;,  which is an Internet standard that allows us to support several things in  email, including multiple parts in message bodies, which is what we need for  this exercise.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The "Content-Type" header is set to &lt;tt&gt;multipart/alternative&lt;/tt&gt;, which tells  the email client that the message is in multiple pieces: one for plain text,  and one for HTML. The "alternative" means that the email client will choose  one or the other based on user settings or the client's limitations.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Finally, on the next line, we add our boundary. This is a random string. The  only real requirement is that it's something that wouldn't occur in the body of  the message.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Notice that the boundary string is preceded by a  space. This is because it's tied to the Content-Type header.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Plain Text Version&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To note the start of the next section of the email, we add our boundary string,  &lt;strong&gt;preceded by two hyphens&lt;/strong&gt;. Then we tell the email client what type of content is  being served, what character set to use, and how to encode it. After that, we  can just add our message text.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="css"&gt;&lt;br /&gt;
--==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx&lt;br /&gt;
Content-Type: text/plain; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit&lt;br /&gt;
&lt;br /&gt;
This Is a Plain Text Email&lt;br /&gt;
&lt;br /&gt;
This message has no HTML. http://w3schools.com&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;The HTML Version&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;For the HTML version of the message, we again start by adding our boundary  string to signify that the next section of the message is starting. Then we add  the content type, character set, and encoding settings, followed by the HTML.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Finally, to end the message, we add the boundary string one more time.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="css"&gt;&lt;br /&gt;
--==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx&lt;br /&gt;
Content-Type: text/html; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;This Is an HTML Email&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This message is composed in &amp;lt;a href="http://w3schools.com"&amp;gt;HTML&amp;lt;/a&amp;gt;.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
--==PHP-alt_xd50dc5b6ee7a015fb67e36ba692a93ad961d5f7dx--&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Sending Multipart Messages with PHP&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Something that really tripped me up when I first started writing scripts to  send emails was the way headers seemed to break depending on how line breaks  were inserted. I spent a lot of time playing with &lt;tt&gt;rn&lt;/tt&gt; and fuming over  seemingly nonsensical glitches until I finally tried the  &lt;a href="http://php.net/heredoc"&gt;heredoc syntax&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To demonstrate one method of sending multipart emails with PHP, let's write a  function to accept an email address and send a message to it with multiple  parts.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Step 1: Write the Function&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;First and foremost, we need to write our function. We're going to call it  &lt;tt&gt;sendEmail()&lt;/tt&gt;, and it will accept one argument, &lt;tt&gt;$to&lt;/tt&gt;, that will  contain the email address.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To start, let's build our subject, headers, and message, then send the message  using &lt;tt&gt;mail()&lt;/tt&gt; and check the success, then output a message to the user  letting them know what happened.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function sendEmail($email)&lt;br /&gt;
{&lt;br /&gt;
	$to = trim($email);&lt;br /&gt;
&lt;br /&gt;
	$subject = "Test Email";&lt;br /&gt;
&lt;br /&gt;
	// Generate a random boundary string&lt;br /&gt;
	$mime_boundary = '_x'.sha1(time()).'x';&lt;br /&gt;
&lt;br /&gt;
	// Using the heredoc syntax to declare the headers&lt;br /&gt;
	$headers = &amp;lt;&amp;lt;&amp;lt;HEADERS&lt;br /&gt;
From: Test &amp;lt;test@example.com&amp;gt;&lt;br /&gt;
MIME-Version: 1.0&lt;br /&gt;
Content-Type: multipart/alternative;&lt;br /&gt;
 boundary="==PHP-alt$mime_boundary"&lt;br /&gt;
HEADERS;&lt;br /&gt;
&lt;br /&gt;
	// Use our boundary string to create plain text and HTML versions&lt;br /&gt;
	$message = &amp;lt;&amp;lt;&amp;lt;MESSAGE&lt;br /&gt;
&lt;br /&gt;
--==PHP-alt$mime_boundary&lt;br /&gt;
Content-Type: text/plain; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit&lt;br /&gt;
&lt;br /&gt;
This Is a Plain Text Email&lt;br /&gt;
&lt;br /&gt;
This message has no HTML. http://w3schools.com&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
This message was generated automatically as a demonstration on&lt;br /&gt;
www.EnnuiDesign.com&lt;br /&gt;
&lt;br /&gt;
If you did not request this message, please notify answers@ennuidesign.com&lt;br /&gt;
&lt;br /&gt;
--==PHP-alt$mime_boundary&lt;br /&gt;
Content-Type: text/html; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit &lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;This Is an HTML Email&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This message is composed in &amp;lt;a href="http://w3schools.com"&amp;gt;HTML&amp;lt;/a&amp;gt;.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
--&amp;lt;br /&amp;gt;&lt;br /&gt;
This message was generated automatically as a demonstration on&lt;br /&gt;
&amp;lt;a href="http://www.ennuidesign.com"&amp;gt;www.EnnuiDesign.com&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
If you did not request this message, please notify &lt;br /&gt;
&amp;lt;a href="mailto:answers@ennuidesign.com"&amp;gt;answers@ennuidesign.com&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
--==PHP-alt$mime_boundary--&lt;br /&gt;
MESSAGE;&lt;br /&gt;
&lt;br /&gt;
	// Send the message&lt;br /&gt;
	if(!mail($to, $subject, $message, $headers))&lt;br /&gt;
	{&lt;br /&gt;
		// If the mail function fails, return an error message&lt;br /&gt;
		return "Something went wrong!";&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// Return a success message if nothing went wrong&lt;br /&gt;
		return "Message sent successfully. Check your email!";&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Step 2: Validate the Email Address&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;We need to verify that an email address submitted to our function is valid  before trying to send an email to it. Otherwise, we could see an internal  server error, which is never fun to see.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To validate our email address, we're going to use a regular expression on our  input after trimming the extra whitespace using  &lt;a href="http://php.net/trim"&gt;&lt;tt&gt;trim()&lt;/tt&gt;&lt;/a&gt;. If the email is valid, we  can safely pass it to the rest of the function.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function sendEmail($email)&lt;br /&gt;
{&lt;br /&gt;
	// This pattern will match email addresses&lt;br /&gt;
	$pattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";&lt;br /&gt;
	if (preg_match($pattern, trim($email)))&lt;br /&gt;
	{&lt;br /&gt;
		// Remove leading and trailing whitespace&lt;br /&gt;
		$to = trim($email);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// Return an error message so the user knows what went wrong&lt;br /&gt;
		return "The email address you entered was invalid. Please try again!";&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	$subject = "Test Email";&lt;br /&gt;
&lt;br /&gt;
	// Generate a random boundary string&lt;br /&gt;
	$mime_boundary = '_x'.sha1(time()).'x';&lt;br /&gt;
&lt;br /&gt;
	// Using the heredoc syntax to declare the headers&lt;br /&gt;
	$headers = &amp;lt;&amp;lt;&amp;lt;HEADERS&lt;br /&gt;
From: Test &amp;lt;test@example.com&amp;gt;&lt;br /&gt;
MIME-Version: 1.0&lt;br /&gt;
Content-Type: multipart/alternative;&lt;br /&gt;
 boundary="==PHP-alt$mime_boundary"&lt;br /&gt;
HEADERS;&lt;br /&gt;
&lt;br /&gt;
	// Use our boundary string to create plain text and HTML versions&lt;br /&gt;
	$message = &amp;lt;&amp;lt;&amp;lt;MESSAGE&lt;br /&gt;
&lt;br /&gt;
--==PHP-alt$mime_boundary&lt;br /&gt;
Content-Type: text/plain; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit&lt;br /&gt;
&lt;br /&gt;
This Is a Plain Text Email&lt;br /&gt;
&lt;br /&gt;
This message has no HTML. http://w3schools.com&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
This message was generated automatically as a demonstration on&lt;br /&gt;
www.EnnuiDesign.com&lt;br /&gt;
&lt;br /&gt;
If you did not request this message, please notify answers@ennuidesign.com&lt;br /&gt;
&lt;br /&gt;
--==PHP-alt$mime_boundary&lt;br /&gt;
Content-Type: text/html; charset="iso-8859-1"&lt;br /&gt;
Content-Transfer-Encoding: 7bit &lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;This Is an HTML Email&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This message is composed in &amp;lt;a href="http://w3schools.com"&amp;gt;HTML&amp;lt;/a&amp;gt;.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
--&amp;lt;br /&amp;gt;&lt;br /&gt;
This message was generated automatically as a demonstration on&lt;br /&gt;
&amp;lt;a href="http://www.ennuidesign.com"&amp;gt;www.EnnuiDesign.com&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
If you did not request this message, please notify &lt;br /&gt;
&amp;lt;a href="mailto:answers@ennuidesign.com"&amp;gt;answers@ennuidesign.com&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
--==PHP-alt$mime_boundary--&lt;br /&gt;
MESSAGE;&lt;br /&gt;
&lt;br /&gt;
	// Send the message&lt;br /&gt;
	if(!mail($to, $subject, $message, $headers))&lt;br /&gt;
	{&lt;br /&gt;
		// If the mail function fails, return an error message&lt;br /&gt;
		return "Something went wrong!";&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// Return a success message if nothing went wrong&lt;br /&gt;
		return "Message sent successfully. Check your email!";&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/multipart_email"&gt;See the Demo&lt;/a&gt; | &lt;a href="/demo/EnnuiDesign_multipart-email.zip"&gt;Download the Source&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This entry was aimed at showing the anatomy of a multipart email message, as  well as demonstrating the use of the heredoc syntax to easily put headers in  place. Additionally, we used a regular expression to match valid email patterns.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Do you have a better regex? How do you handle headers? Let me know in the  comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/Send+HTML+and+Plain+Text+Versions+of+Email"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tAssGMKYsZ6uDJlNe2hxyazfsAY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tAssGMKYsZ6uDJlNe2hxyazfsAY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tAssGMKYsZ6uDJlNe2hxyazfsAY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tAssGMKYsZ6uDJlNe2hxyazfsAY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/zsTfLaHZhm4" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/zsTfLaHZhm4/Send+HTML+and+Plain+Text+Versions+of+Email</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/Send+HTML+and+Plain+Text+Versions+of+Email</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/Send+HTML+and+Plain+Text+Versions+of+Email</feedburner:origLink></item>
    <item>
      <title>ITT #16: Create a Template Parsing System with PHP</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1242777491_67892.jpg" alt="Using a template to ease the editing of pages" /&gt;&lt;br /&gt;&lt;p&gt;One of my most recent obsessions has been with simplifying my custom CMS to  allow me to generate full sites without changing anything but HTML template  files and a basic configuration file. In this week's  &lt;a href="blog/tag/instant+tip+tuesday"&gt;Instant Tip  Tuesday&lt;/a&gt;, we'll explore one of the ways we can dynamically generate output and wrap it in a template file.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This is a proof-of-concept type of thing, not a  production-ready script. Be aware that I haven't used a script like this on  a real site, and therefore have no idea if it's fast, effective, or even  useful. For now, this is just a "hey, cool!" sort of thing; use with  discretion.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/EnnuiDesign_templating.zip"&gt;Download the Files&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;So, What Are We Trying to Do?&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;To try and explain what our goal is, here, let's look at a couple examples. For  our examples, we'll be using the following simple array:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
$entries = array(&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Title One',&lt;br /&gt;
		'entry' =&amp;gt; 'This is some text.'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Title Two',&lt;br /&gt;
		'entry' =&amp;gt; 'This is some more text.'&lt;br /&gt;
	)&lt;br /&gt;
);&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;The Usual Method&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In a traditional script, we would need to write something similar to the  following in order to output both entries in clean HTML:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
foreach($entries as $e) {&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;h1&amp;gt; &amp;lt;?php echo $e['title'] ?&amp;gt; &amp;lt;/h1&amp;gt;&lt;br /&gt;
	&amp;lt;p&amp;gt; &amp;lt;?php echo $e['entry'] ?&amp;gt; &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
} // End foreach&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;While this isn't bad, it can get confusing. It's especially tricky when we  start dealing with entries that have more elements, such as the author, date  posted, images, and so on.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Template Method&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;What if we could put together some scripts that would allow us to simply edit  an HTML file to lay out our pages:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;h1&amp;gt; {title} &amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt; {entry} &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;That's it. Seriously.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To use this in our scripts, we just call a quick function between the  &lt;tt&gt;&amp;lt;body&amp;gt;&lt;/tt&gt; tags of our public HTML file:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
	&amp;lt;title&amp;gt; Template Testing &amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
	&amp;lt;?php displayEntries($entries, $template) ?&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Each entry would be processed and formatted according the template we specified  in an external, easy to edit file.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;How Do We Do That?&lt;/h2&gt;&lt;br /&gt;
&lt;h3&gt;Planning Our Steps&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In order to parse a template file, we're going to need to use several advanced  programming techniques. The steps we'll be using are:&lt;/p&gt;&lt;br /&gt;
&lt;ol&gt;&lt;br /&gt;
&lt;li&gt;Build a public HTML page to act as a container&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Build a template file&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Load the contents of the template file into a variable&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Run a regular expression to find all template tags&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Use &lt;tt&gt;preg_replace_callback()&lt;/tt&gt; with a &lt;em&gt;currying&lt;/em&gt; function to  send the matches to a replacement function&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Match the template tag text with an array index and use the corresponding  data from the array&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Set up a loop that will use the template for each entry in the array&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h3&gt;Setting Up Our Project&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;This project will consist of three files:&lt;/p&gt;&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;index.php&lt;/tt&gt; &amp;mdash; The public HTML file&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;template.html&lt;/tt&gt; &amp;mdash; The entry template&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;tt&gt;functions.php&lt;/tt&gt; &amp;mdash; Our parsing functions&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;h2&gt;Step 1 &amp;mdash; Build a Public HTML Page&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Because this is a very basic example, our container file (&lt;tt&gt;index.php&lt;/tt&gt;)  will be very basic. Create the file and insert the following code into it:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
	&amp;lt;title&amp;gt; Template Testing &amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This file will eventually call the function that displays our entries.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 2 &amp;mdash; Build a Template File&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Again, with this being an extremely simple example, our &lt;tt&gt;template.html&lt;/tt&gt; file is only two lines:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;h1&amp;gt; {title} &amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt; {entry} &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;We're going to use curly braces to wrap our template tags. These tags need to correspond to a key in our array, so to access &lt;tt&gt;$entry['title']&lt;/tt&gt; we need  to use &lt;tt&gt;{title}&lt;/tt&gt;. This will work for any named array index, so if we  want to manipulate data, we can just add a new named value to the array.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 3 &amp;mdash; Loading the Template&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This step is the easiest. Our template from above will be saved in an external  HTML file called &lt;tt&gt;template.html&lt;/tt&gt;. In order to perform our replacement  functions on the contents of the file, we need to load the entire file as into  a variable in &lt;tt&gt;index.php&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Load the template into a variable&lt;br /&gt;
$template = file_get_contents('template.html');&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Now we have the contents of &lt;tt&gt;template.html&lt;/tt&gt; available to run our regular  expression with.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 4 &amp;mdash; Parse the Template with a Regular Expression&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;At this point, we have a file to display our output, and a template to shape  our output. All that's left to do is write the scripts that will fit our data  into the template.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;As we move into this code, it might look a little overwhelming at first. We'll step through everything by the end of the article, though.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Regular Expression&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In order to find our template tags, we need to locate any data enclosed within  curly braces. The data needs to be a letter with no spaces or punctuation  except underscores. To accomplish this, we use the following regular  expression:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
$pattern = "/{(w+?)}/"; // Matches any template tag&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The basics of what we're doing here go something like this: we start and finish  with a forward slash because these are delimiters for regular expressions; the  curly braces need to be escaped because they are special characters, so we use  a backslash to do so (&lt;tt&gt;{&lt;/tt&gt;); to capture the tag name for later use, we  need to enclose it in parentheses, which means we can access it as a match  later; the &lt;tt&gt;w+&lt;/tt&gt; means, "match any word character (a-z and underscores)  one or more times"; the question mark means the expression is lazy and will  stop matching at the first closing curly brace it finds.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;That's a lame crash course in regular expressions, but that's not our focus  today. We can rest assured knowing that it works and move on.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Parsing the Template&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Armed with our regular expression, we need to use  &lt;a href="http://php.net/preg_replace_callback"&gt;&lt;tt&gt;preg_replace_callback()&lt;/tt&gt;&lt;/a&gt; to parse our template. The way this works is that we supply a pattern, a  function to be called on the matches, and the string on which we're running the  regex.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We have to jump ahead a little bit here, so stay with me. The callback function  we're passing to &lt;tt&gt;preg_replace_callback()&lt;/tt&gt; is going to be a  &lt;em&gt;currying&lt;/em&gt; function. We'll get to what that is and how it works in just  a minute.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Parsing Function&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;With the regex ready and an idea of how we need to parse the template, we can  write our function, called &lt;tt&gt;parseTemplate()&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function parseTemplate($replacement_array, $template)&lt;br /&gt;
{&lt;br /&gt;
	$pattern = "/{(w+?)}/i"; // Matches any template tag&lt;br /&gt;
&lt;br /&gt;
	/* &lt;br /&gt;
	 * Call the currying function, tell it to accept two&lt;br /&gt;
	 * arguments, and only pass it one: the array containing&lt;br /&gt;
	 * values to replace the tags with.&lt;br /&gt;
	 */&lt;br /&gt;
	$callback = curry('replaceTags', 2);&lt;br /&gt;
&lt;br /&gt;
	return preg_replace_callback($pattern, $callback($replacement_array), $template);&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Step 5 &amp;mdash; Currying&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This is by far the most complicated part of this project.  &lt;a href="http://en.wikipedia.org/wiki/Currying"&gt;Currying&lt;/a&gt; is a concept  by which we can call a function &lt;em&gt;halfway&lt;/em&gt;. Essentially, we're able to  call, for instance, a function that accepts two arguments, but only pass one of  the arguments, storing a new function in a variable that will allow us to pass  the other argument and complete the function later.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Because I don't know all of the theory behind currying, I'm not going to get  into a whole lot of detail lest I put my foot in my mouth. All we need to know  for this project is that using currying, we'll be able to pass a half-cocked  replacement function with our entry array to &lt;tt&gt;preg_replace_callback()&lt;/tt&gt;,  then add the matches returned into the mix and come up with a properly parsed  template.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The currying function looks like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function curry($func, $arity) {&lt;br /&gt;
	/* &lt;br /&gt;
	 * Creates an anonymous function to accept incomplete&lt;br /&gt;
	 * argument lists and allow the rest of the arguments&lt;br /&gt;
	 * to be supplied later&lt;br /&gt;
	 */ &lt;br /&gt;
	return create_function('', "&lt;br /&gt;
		// Get an array of the arguments passed to $func&lt;br /&gt;
		$args = func_get_args();&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * If the number of arguments supplied to the passed&lt;br /&gt;
		 * function is greater than or equal to the number of &lt;br /&gt;
		 * arguments defined in $arity, call the function and&lt;br /&gt;
		 * return its output&lt;br /&gt;
		 */&lt;br /&gt;
		if(count($args) &amp;gt;= $arity)&lt;br /&gt;
		{&lt;br /&gt;
			return call_user_func_array('$func', $args);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Otherwise, save the function paramters in a variable&lt;br /&gt;
		 * and return a function that will accept more parameters&lt;br /&gt;
		 * while preserving the original passed arguments&lt;br /&gt;
		 */&lt;br /&gt;
		$args = var_export($args, 1);&lt;br /&gt;
		return create_function('','&lt;br /&gt;
			$a = func_get_args();&lt;br /&gt;
			$z = ' . $args . ';&lt;br /&gt;
			$a = array_merge($z,$a);&lt;br /&gt;
			return call_user_func_array('$func', $a);&lt;br /&gt;
		');&lt;br /&gt;
	");&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;When we called our currying function, we pass &lt;tt&gt;replaceTags()&lt;/tt&gt; as the  first parameter, and &lt;tt&gt;2&lt;/tt&gt; as the second parameter. This means that we are  creating an anonymous function that will accept two parameters. We then pass  the replacement array as the first parameter in  &lt;tt&gt;preg_replace_callback()&lt;/tt&gt;. The returned matches are passed as the second  parameter when the callback fires, effectively completing  &lt;tt&gt;replaceTags()&lt;/tt&gt; and returning our parsed template.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 6 &amp;mdash; Match the Template with Our Array&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;We're ready to write the function &lt;tt&gt;replaceTags()&lt;/tt&gt; that is called by  our currying function. This is a pretty straightforward function, in which we check that the template tag exists in the array as a key, then return the  value. If the tag doesn't exist, the tag is returned as plain text.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;When we write our funciton, it looks like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function replaceTags($transformations, $matches)&lt;br /&gt;
{&lt;br /&gt;
	// To avoid errors, make sure the array contains a key that matches&lt;br /&gt;
	if(array_key_exists($matches[1], $transformations))&lt;br /&gt;
	{&lt;br /&gt;
		// Return the array value whose key matches the template tag&lt;br /&gt;
		return $transformations[strtolower($matches[1])];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If not, return the template tag as is&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return '{'.$matches[1].'}';&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Step 7 &amp;mdash; Loop Through the Entries&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;We're pretty much done at this point. All we need is one more function to loop  through our entry array and put each one into the template.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Our function, called &lt;tt&gt;displayEntries()&lt;/tt&gt;, simply sets up a  &lt;tt&gt;foreach&lt;/tt&gt; loop and pushes each array item through the template parsing  functions, echoing the output to the browser. We could just as easily store the  output in a variable, but for this example it's not necessary.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function displayEntries($entries, $template)&lt;br /&gt;
{&lt;br /&gt;
	foreach($entries as $e)&lt;br /&gt;
	{&lt;br /&gt;
		echo parseTemplate($e, $template);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Putting Everything Together&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;To implement our functions, simply add the following to the top of  &lt;tt&gt;index.php&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Include the parsing functions&lt;br /&gt;
include_once 'functions.php';&lt;br /&gt;
&lt;br /&gt;
// Load the template into a variable&lt;br /&gt;
$template = file_get_contents('template.html');&lt;br /&gt;
&lt;br /&gt;
// Grab the information we need to parse&lt;br /&gt;
$entries = loadEntries();&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Notice we're using a function called &lt;tt&gt;loadEntries()&lt;/tt&gt;. On a live site,  this would probably grab entries from a database. In this example, the function  simply returns the array we declared above:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function loadEntries()&lt;br /&gt;
{&lt;br /&gt;
	return array(&lt;br /&gt;
		array(&lt;br /&gt;
			'title' =&amp;gt; 'Title One',&lt;br /&gt;
			'entry' =&amp;gt; 'This is some text.'&lt;br /&gt;
		),&lt;br /&gt;
		array(&lt;br /&gt;
			'title' =&amp;gt; 'Title Two',&lt;br /&gt;
			'entry' =&amp;gt; 'This is some more text.'&lt;br /&gt;
		)&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;We'll place &lt;tt&gt;loadEntries()&lt;/tt&gt; in &lt;tt&gt;functions.php&lt;/tt&gt; for easy access.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The final step is to call &lt;tt&gt;displayEntries&lt;/tt&gt; between the  &lt;tt&gt;&amp;lt;body&amp;gt;&lt;/tt&gt; tags to output our templated entries. The finished  &lt;tt&gt;index.php&lt;/tt&gt; looks like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Include the parsing functions&lt;br /&gt;
include_once 'functions.php';&lt;br /&gt;
&lt;br /&gt;
// Load the template into a variable&lt;br /&gt;
$template = file_get_contents('template.html');&lt;br /&gt;
&lt;br /&gt;
// Grab the information we need to parse&lt;br /&gt;
$entries = loadEntries();&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
	&amp;lt;title&amp;gt; Template Testing &amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
	&amp;lt;?php displayEntries($entries, $template) ?&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="/demo/EnnuiDesign_templating.zip"&gt;Download the Files&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;In this entry, we created a simple templating system as a proof of concept. We  also explored currying functions and regular expressions on a basic level.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;What do you think? Any ideas for improvements? Any constructive criticism? I'm  all ears! Hit me in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2316%3A+Create+a+Template+Parsing+System+with+PHP"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3Tmi2vBZznXx8goT53YSySTZ7LI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3Tmi2vBZznXx8goT53YSySTZ7LI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3Tmi2vBZznXx8goT53YSySTZ7LI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3Tmi2vBZznXx8goT53YSySTZ7LI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/jCE1w-EtRAI" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/jCE1w-EtRAI/ITT+%2316%3A+Create+a+Template+Parsing+System+with+PHP</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2316%3A+Create+a+Template+Parsing+System+with+PHP</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2316%3A+Create+a+Template+Parsing+System+with+PHP</feedburner:origLink></item>
    <item>
      <title>ITT #15: Create a Simple Contact Form</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1242180007_81734.jpg" alt="Get mail right through your site" /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This entry has been improved upon by adding spam protection and sessions. It's strongly recommended that you use the &lt;a href="../blog/Improving+the+Simple+Contact+Form"&gt;newer version of the simple contact form&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Making yourself accessible is one of the most important aspects of a site that  aims to connect with its audience online, and nothing makes a person more  accessible than an easy-to-use contact form.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;In this week's &lt;a href="../tag/instant+tip+tuesday"&gt;Instant Tip  Tuesday&lt;/a&gt;, we'll build a simple (less than 200 lines of code, including  comments) contact form that will allow users to contact us without needing to  open their mail client or copy and paste our email address into their web mail  service. Our finished contact form will do the following:&lt;/p&gt;&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;Accept the user's name, email, URL, and a message&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Verify that required fields were filled out&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Validate the supplied email address&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Send the user's message to an email address of our choice&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Send the user a confirmation that their message was sent&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="../../demo/contact_form"&gt;View the Demo&lt;/a&gt; | &lt;a href="../../demo/EnnuiDesign_contact-form.zip"&gt;Download the Files&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 1 &amp;mdash; The Message Form&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Our first step is to generate the form so that our user can create their  message. As we decided above, we want to accept the user's name, email address,  website URL, and a message.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Because we're all savvy with HTML, we won't cover the "why" for the following  code. The following is valid XHTML 1.0 Strict:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;h1&amp;gt; Simple Contact Form &amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;form action="inc/contact.inc.php" method="post" id="cf"&amp;gt;&lt;br /&gt;
	&amp;lt;fieldset&amp;gt;&lt;br /&gt;
		&amp;lt;legend&amp;gt;Send a Message&amp;lt;/legend&amp;gt;&lt;br /&gt;
		&amp;lt;label for="cf_n"&amp;gt;Name (required)&amp;lt;/label&amp;gt;&lt;br /&gt;
		&amp;lt;input id="cf_n" name="cf_n" type="text" maxlength="75" /&amp;gt;&lt;br /&gt;
		&amp;lt;label for="cf_e"&amp;gt;Email (required)&amp;lt;/label&amp;gt;&lt;br /&gt;
		&amp;lt;input id="cf_e" name="cf_e" type="text" maxlength="150" /&amp;gt;&lt;br /&gt;
		&amp;lt;label for="cf_w"&amp;gt;Website (optional)&amp;lt;/label&amp;gt;&lt;br /&gt;
		&amp;lt;input id="cf_w" name="cf_w" type="text" maxlength="150" /&amp;gt;&lt;br /&gt;
		&amp;lt;label for="cf_m"&amp;gt;Enter Your Message Here&amp;lt;/label&amp;gt;&lt;br /&gt;
		&amp;lt;textarea id="cf_m" name="cf_m" rows="14" cols="45"&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;
		&amp;lt;input type="submit" name="submit" class="submit" value="Send" /&amp;gt;&lt;br /&gt;
		&amp;lt;input type="submit" name="submit" class="submit" value="Cancel" /&amp;gt;&lt;br /&gt;
	&amp;lt;/fieldset&amp;gt;&lt;br /&gt;
&amp;lt;/form&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;We won't go into details on the styling of the form so that we can focus on the  processing, but feel free to take a look at the CSS in  &lt;a href="../../demo/contact_form"&gt;the demo&lt;/a&gt; for a starting point.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 2 &amp;mdash; Processing the Form&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;When the user submits the form, it sends the information via the &lt;tt&gt;POST&lt;/tt&gt; method to the file &lt;tt&gt;inc/contact.inc.php&lt;/tt&gt;. Our next step is to write the  script that will process the input and send the message.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Validate the Data&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Before sending any messages, we need to make sure that the user actually filled  out the form and entered valid information. To do this, we first verify that  the &lt;tt&gt;POST&lt;/tt&gt; method was used to access the script and that the "Send"  button was pressed to submit the form.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;After that, we simply check that each form is not empty (and also not equal to  the value of the field's label), then store the information in a variable. The email address is special, which we'll talk about in a minute.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * If the form was submitted and the "Send" button pressed, &lt;br /&gt;
 * continue processing the data&lt;br /&gt;
 */&lt;br /&gt;
if($_SERVER['REQUEST_METHOD']=='POST' &amp;amp;&amp;amp; $_POST['submit']=='Send')&lt;br /&gt;
{&lt;br /&gt;
	$err = NULL;&lt;br /&gt;
&lt;br /&gt;
	// If the name field was filled out, sanitize the input and store it&lt;br /&gt;
	if(!empty($_POST['cf_n']) &amp;amp;&amp;amp; $_POST['cf_n']!='Name (required)')&lt;br /&gt;
	{&lt;br /&gt;
		$name = htmlentities($_POST['cf_n'], ENT_QUOTES);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// If the name wasn't entered, create an error message&lt;br /&gt;
		$err .= "Please enter your name!&amp;lt;br /&amp;gt;";&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If the email is set, validate and store it&lt;br /&gt;
	if(!empty($_POST['cf_e']) &amp;amp;&amp;amp; $_POST['cf_e']!='Email (required)')&lt;br /&gt;
	{&lt;br /&gt;
		// Define a regex pattern to validate the email address&lt;br /&gt;
		$pattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";&lt;br /&gt;
			if (preg_match($pattern, $_POST['cf_e']))&lt;br /&gt;
			{&lt;br /&gt;
				$email = $_POST['cf_e'];&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				// If the email doesn't match the pattern, error&lt;br /&gt;
				$err .= "Please enter a valid email address!&amp;lt;br /&amp;gt;";&lt;br /&gt;
			}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If no email was entered, generate an error message&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		$err .= "Please enter a valid email address!&amp;lt;br /&amp;gt;";&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Check the website field&lt;br /&gt;
	if(!empty($_POST['cf_w']) &amp;amp;&amp;amp; $_POST['cf_w']!='Website (optional)')&lt;br /&gt;
	{&lt;br /&gt;
		$site = htmlentities($_POST['cf_w'], ENT_QUOTES);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// Because the website is optional, no error if empty&lt;br /&gt;
		$site = "none";&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Ensure a message was entered, then sanitize it&lt;br /&gt;
	if(!empty($_POST['cf_m']) &amp;amp;&amp;amp; $_POST['cf_m']!='Enter Your Message Here')&lt;br /&gt;
	{&lt;br /&gt;
		$message = strip_tags($_POST['cf_m']);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If no message was entered, adds an error message&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		$err .= "Please enter a message!&amp;lt;br /&amp;gt;";&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Process the sanitized and validated data&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
	 * If the wrong request method was used or the "Send" button&lt;br /&gt;
	 * wasn't pressed (i.e. "Cancel" was pressed), return the user&lt;br /&gt;
	 * to the contact form with no message.&lt;br /&gt;
	 */&lt;br /&gt;
	header("Location: ../");&lt;br /&gt;
	exit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;As noted in the comments above, each submitted field is checked, then sanitized  and saved in a variable.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;If any of our required fields aren't properly filled out, we store a message  in the variable &lt;tt&gt;$err&lt;/tt&gt;. Note that we are appending messages to the  variable rather than overwriting the variable. This way, we're able to tell  the user every error that occurred, rather than just the last one.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The email check is performed by using a regex pattern, then matching the user  input against the pattern using  &lt;a href="http://us3.php.net/manual/en/function.preg-match.php"&gt;&lt;tt&gt;preg_match()&lt;/tt&gt;&lt;/a&gt;. If a match is found, this means the email is valid, so we save it in a  variable.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Process the Data&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Now that we have our data stored, we're ready to start sending messages. First,  we need to ensure that no errors occurred. Since the &lt;tt&gt;$err&lt;/tt&gt; variable is  &lt;tt&gt;NULL&lt;/tt&gt; by default, we can check if it's set to catch any errors.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;If an error occurred, we simply display the stored error messages and provide  a link to try again. (NOTE: In a production environment, it would probably be a  good idea to store the input in a session to prevent the user from needing to  re-enter their message. This was left out in the interest of keeping this tip  short and to-the-point.)&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;If no errors occurred, we place the supplied information into an email message  and fire it off to the designated email address. Then, if the first message  sent successfully, we send the user a confirmation email.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;All of that functionality is accomplished with this code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
	// Validate and sanitize the input (see above)&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * With the data sanitized, we need to check for errors to ensure&lt;br /&gt;
	 * that the message is valid before sending it&lt;br /&gt;
	 */&lt;br /&gt;
	if(isset($err))&lt;br /&gt;
	{&lt;br /&gt;
		echo '&amp;lt;h1&amp;gt; Oops! &amp;lt;/h1&amp;gt;', $err, '&amp;lt;br /&amp;gt;&amp;lt;a href="../"&amp;gt;Try again!&amp;lt;/a&amp;gt;';&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * If no errors occurred, send the message&lt;br /&gt;
	 */&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		$to = "Ennui Design &amp;lt;answers@ennuidesign.com&amp;gt;";&lt;br /&gt;
		$subject = "[Ennui Design] Message from the Ennui Design contact form";&lt;br /&gt;
		$headers = &amp;lt;&amp;lt;&amp;lt;MESSAGE_HEADER&lt;br /&gt;
From: $name &amp;lt;$email&amp;gt;&lt;br /&gt;
Content-Type: text/plain&lt;br /&gt;
MESSAGE_HEADER;&lt;br /&gt;
		$msg = &amp;lt;&amp;lt;&amp;lt;MESSAGE_BODY&lt;br /&gt;
Name:  $name&lt;br /&gt;
Email: $email&lt;br /&gt;
URL:   $site&lt;br /&gt;
&lt;br /&gt;
Message:&lt;br /&gt;
&lt;br /&gt;
$message&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
This message was sent via the contact form on EnnuiDesign.com&lt;br /&gt;
MESSAGE_BODY;&lt;br /&gt;
		if(!mail($to, $subject, $msg, $headers))&lt;br /&gt;
		{&lt;br /&gt;
			header("Location: ../?send=error");&lt;br /&gt;
			exit;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Now send a confirmation email to the user.&lt;br /&gt;
		$conf_to  = "$name &amp;lt;$email&amp;gt;";&lt;br /&gt;
		$conf_sub = "Thank You for Contacting Us!";&lt;br /&gt;
		$conf_headers = &amp;lt;&amp;lt;&amp;lt;MESSAGE_HEADER&lt;br /&gt;
From: Ennui Design &amp;lt;donotreply@ennuidesign.com&amp;gt;&lt;br /&gt;
Content-Type: text/plain&lt;br /&gt;
MESSAGE_HEADER;&lt;br /&gt;
		$conf_message = &amp;lt;&amp;lt;&amp;lt;MESSAGE_BODY&lt;br /&gt;
Thank you for contacting us! Your message&lt;br /&gt;
was sent successfully, and we will get back&lt;br /&gt;
to you as quickly as possible.&lt;br /&gt;
&lt;br /&gt;
All the Best,&lt;br /&gt;
Ennui Design&lt;br /&gt;
&lt;br /&gt;
answers@ennuidesign.com&lt;br /&gt;
www.EnnuiDesign.com&lt;br /&gt;
MESSAGE_BODY;&lt;br /&gt;
		if(!mail($conf_to, $conf_sub, $conf_message, $conf_headers))&lt;br /&gt;
		{&lt;br /&gt;
			header("Location: ../?send=error");&lt;br /&gt;
			exit;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Send the user back to the main page&lt;br /&gt;
		header('Location: ../?send=successful');&lt;br /&gt;
		exit;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Remainder of script (see above)&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To send an email with PHP in plain text, all we have to do is put together a  "to" address, a subject, the message itself, and the message headers (such as  the content type and "from" address). With the message assembled, we simply run  the &lt;a href="http://us3.php.net/manual/en/function.mail.php"&gt;&lt;tt&gt;mail()&lt;/tt&gt;&lt;/a&gt; function and check that it fired successfully. If either call fails, we send  the user back to the contact form with an error code in the URL to allow for a  message to be displayed.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Make It Pretty&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To add some client-side form validation, we'll implement the  &lt;a href="../Beautiful+Forms+with+JavaScript"&gt;beautiful-forms.js&lt;/a&gt; script featured on Ennui Design a few months back. This is done by adding the  following to the form HTML:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
&amp;lt;script type="text/javascript" src="js/beautiful-forms.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;
	var formId = "cf";&lt;br /&gt;
	var reqFields = new Array('cf_n','cf_e','cf_m');&lt;br /&gt;
	if ( document.getElementById(formId) ) {&lt;br /&gt;
		prettyForms("cf", reqFields);&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;For an explanation of how and why this works,  &lt;a href="../Beautiful+Forms+with+JavaScript"&gt;read  about JavaScript form validation with beautiful-forms.js&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;span class="demolink"&gt;&lt;a href="../../demo/contact_form"&gt;View the Demo&lt;/a&gt; | &lt;a href="../../demo/EnnuiDesign_contact-form.zip"&gt;Download the Files&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;This contact form is quick and dirty, but it will easily get you up and running  with a new point of contact for your users. What do you use to make yourself  accessible to users? How would you improve the contact form above? Let me know  in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2315%3A+Create+a+Simple+Contact+Form"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/B7M3EWp-sOQpTPoWEZMyA4Uy1Ks/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/B7M3EWp-sOQpTPoWEZMyA4Uy1Ks/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/B7M3EWp-sOQpTPoWEZMyA4Uy1Ks/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/B7M3EWp-sOQpTPoWEZMyA4Uy1Ks/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/cRPxaudW1BU" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/cRPxaudW1BU/ITT+%2315%3A+Create+a+Simple+Contact+Form</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2315%3A+Create+a+Simple+Contact+Form</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2315%3A+Create+a+Simple+Contact+Form</feedburner:origLink></item>
    <item>
      <title>ITT #14: Optimizing MySQL Queries</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1241566391_72292.jpg" alt="Get it? Joined tables?" /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;DISCLAIMER: I am by no means a MySQL optimization expert, and I can't  guarantee that the information provided in this blog entry will take a query  from painfully slow to blazing fast. I can, however, guarantee that this entry  was written with the best intentions and aims to explore some of the more  advanced features of MySQL.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This week, I wanted to share some of my recent experiments with MySQL queries  in regard to lowering the number of requests sent to the database server and,  hopefully, avoiding the bottleneck that can form on sites that rely heavily on  database interaction.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;What Are MySQL Joins?&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;A &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/join.html"&gt;&lt;tt&gt;JOIN&lt;/tt&gt;&lt;/a&gt; in MySQL is a tool that allows developers to &lt;strong&gt;combine one or more tables in a  query&lt;/strong&gt;. There are a few flavors of &lt;tt&gt;JOIN&lt;/tt&gt;, but we'll be focusing on  &lt;tt&gt;LEFT JOIN&lt;/tt&gt; today.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;A &lt;tt&gt;LEFT JOIN&lt;/tt&gt; in MySQL combines rows from two tables. We're able to  narrow our searches as usual using a &lt;tt&gt;WHERE&lt;/tt&gt; clause, and we can specify  how the tables are joined with a &lt;tt&gt;USING&lt;/tt&gt; clause.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;A Simple Example&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;It's tough to explain &lt;tt&gt;JOIN&lt;/tt&gt; in plain English without getting lost in a  bunch of technical jargon (as I'm sure anyone who ventures into the MySQL  manual is already aware). It's far easier to provide a concrete example to  illustrate the way that &lt;tt&gt;LEFT JOIN&lt;/tt&gt; works.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We'll be using three tables in this example: &lt;tt&gt;users&lt;/tt&gt;, &lt;tt&gt;lists&lt;/tt&gt;,  and &lt;tt&gt;items&lt;/tt&gt;. These three tables will be the basis of a theoretical wish list application, with a user's unique ID and name stored in the &lt;tt&gt;users&lt;/tt&gt; table, unique list ID and user ID stored in &lt;tt&gt;lists&lt;/tt&gt;, and individual item IDs, containing list ID, and item text in the &lt;tt&gt;items&lt;/tt&gt; table.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
Table: users&lt;br /&gt;
+---------+-----------------+&lt;br /&gt;
| user_id | user_name       |&lt;br /&gt;
+---------+-----------------+&lt;br /&gt;
| 1       | Jason Lengstorf |&lt;br /&gt;
+---------+-----------------+&lt;br /&gt;
| 2       | John Doe        |&lt;br /&gt;
+---------+-----------------+&lt;br /&gt;
&lt;br /&gt;
Table: lists&lt;br /&gt;
+---------+---------+&lt;br /&gt;
| list_id | user_id |&lt;br /&gt;
+---------+---------+&lt;br /&gt;
| 1       | 2       |&lt;br /&gt;
+---------+---------+&lt;br /&gt;
| 2       | 1       |&lt;br /&gt;
+---------+---------+&lt;br /&gt;
&lt;br /&gt;
Table: items&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| item_id | list_id | item_text            |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| 1       | 1       | iPod Touch           |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| 2       | 1       | Chuck Season 2       |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| 3       | 1       | Nike Free Shoes      |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| 4       | 2       | F-Stop Maverick Bag  |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| 5       | 2       | Bon Iver Tickets     |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
| 6       | 2       | Rogue Mocha Porter   |&lt;br /&gt;
+---------+---------+----------------------+&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Imagine we've been supplied with a user's ID and need to &lt;strong&gt;retrieve the items  on his wish list&lt;/strong&gt;. Without using &lt;tt&gt;JOIN&lt;/tt&gt;, we would need two MySQL queries: one to retrieve the list ID associated with the user, and one to retrieve all  the items associated with that list ID.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Example 1 (Not Using &lt;tt&gt;JOIN&lt;/tt&gt;)&lt;/h3&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
	// Establish a MySQL connection&lt;br /&gt;
	$link = new PDO(DBINFO, DBUSER, DBPASS);&lt;br /&gt;
&lt;br /&gt;
	// Retrieve the list ID associated with the user ID&lt;br /&gt;
	$sql = "SELECT list_id&lt;br /&gt;
			FROM lists&lt;br /&gt;
			WHERE user_id = ?&lt;br /&gt;
			LIMIT 1";&lt;br /&gt;
	$stmt = $link-&amp;gt;prepare($sql); // Prepare the statement&lt;br /&gt;
	if($stmt-&amp;gt;execute(array($_POST['user_id'])))&lt;br /&gt;
	{&lt;br /&gt;
		$row = $stmt-&amp;gt;fetch(); // Load the results in an array&lt;br /&gt;
		$list_id = $row['list_id'];&lt;br /&gt;
		$stmt-&amp;gt;closeCursor(); // Free memory used in this query&lt;br /&gt;
&lt;br /&gt;
		// Retrieve the items associated with the list ID&lt;br /&gt;
		$sql = "SELECT item_text&lt;br /&gt;
				FROM items&lt;br /&gt;
				WHERE list_id = $list_id";&lt;br /&gt;
		foreach($link-&amp;gt;query($sql) as $row) {&lt;br /&gt;
			// Output the wish list items&lt;br /&gt;
			echo $row['item_text'], "&amp;lt;br /&amp;gt;";&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Assuming the user has supplied the user id of 1, we would see the following  output:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
F-Stop Maverick Bag&lt;br /&gt;
Bon Iver Tickets&lt;br /&gt;
Rogue Mocha Porter&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This returns the desired result, but sending two queries just feels  inefficient. Fortunately, we can &lt;strong&gt;shorten this script to just one query using a &lt;tt&gt;JOIN&lt;/tt&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Example 1 (Using &lt;tt&gt;JOIN&lt;/tt&gt;)&lt;/h3&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
	// Establish a MySQL connection&lt;br /&gt;
	$link = new PDO(DBINFO, DBUSER, DBPASS);&lt;br /&gt;
&lt;br /&gt;
	// Retrieve the items associated with the user ID&lt;br /&gt;
	$sql = "SELECT item_text&lt;br /&gt;
			FROM lists&lt;br /&gt;
			LEFT JOIN items&lt;br /&gt;
			USING (list_id)&lt;br /&gt;
			WHERE user_id = ?";&lt;br /&gt;
	$stmt = $link-&amp;gt;prepare($sql); // Prepare the statement&lt;br /&gt;
	if($stmt-&amp;gt;execute(array($_POST['user_id'])))&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		// Loop through the returned results&lt;br /&gt;
		while($row = $stmt-&amp;gt;fetch()) {&lt;br /&gt;
			// Output the wish list items&lt;br /&gt;
			echo $row['item_text'], "&amp;lt;br /&amp;gt;";&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		$stmt-&amp;gt;closeCursor(); // Free memory used in this query&lt;br /&gt;
	}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Using a &lt;tt&gt;LEFT JOIN&lt;/tt&gt;, we were able to &lt;strong&gt;combine the &lt;tt&gt;lists&lt;/tt&gt; and  &lt;tt&gt;items&lt;/tt&gt; tables&lt;/strong&gt;, grouping entries by their list IDs. Essentially, by  using a &lt;tt&gt;JOIN&lt;/tt&gt;, we're temporarily creating a new table that looks like  this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
SELECT * FROM lists LEFT JOIN items USING (list_id)&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| list_id | user_id | item_id | item_text           |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| 1       | 2       | 1       | iPod Touch          |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| 1       | 2       | 2       | Chuck Season 2      |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| 1       | 2       | 3       | Nike Free Shoes     |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| 2       | 1       | 4       | F-Stop Maverick Bag |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| 2       | 1       | 5       | Bon Iver Tickets    |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
| 2       | 1       | 6       | Rogue Mocha Porter  |&lt;br /&gt;
+---------+---------+---------+---------------------+&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;With all the information available from both tables, we're able to &lt;strong&gt;use our  user's ID to directly select wish list items. &lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Going a Step Further&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Our wish list isn't very useful if it only shows a list of products. In order  to make any sense, we should probably &lt;strong&gt;show the user's name&lt;/strong&gt; to indicate who it  is that wants the displayed items.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This presents a problem for us, however, because &lt;strong&gt;we now need to pull  information from all three tables&lt;/strong&gt; in order to gather all the necessary data.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Example 2 &amp;mdash; Combining Three Tables Using &lt;tt&gt;LEFT JOIN&lt;/tt&gt;&lt;/h3&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
	// Establish a MySQL connection&lt;br /&gt;
	$link = new PDO(DBINFO, DBUSER, DBPASS);&lt;br /&gt;
&lt;br /&gt;
	// Retrieve the user's name and associated list items&lt;br /&gt;
	$sql = "SELECT user_name, item_text&lt;br /&gt;
			FROM users&lt;br /&gt;
			LEFT JOIN lists&lt;br /&gt;
			USING (user_id)&lt;br /&gt;
			LEFT JOIN items&lt;br /&gt;
			USING (list_id)&lt;br /&gt;
			WHERE user_id = ?";&lt;br /&gt;
	$stmt = $link-&amp;gt;prepare($sql); // Prepare the statement&lt;br /&gt;
	if($stmt-&amp;gt;execute(array($_POST['user_id'])))&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		// Loop through the returned results&lt;br /&gt;
		while($row = $stmt-&amp;gt;fetch()) {&lt;br /&gt;
&lt;br /&gt;
			// Save the user name&lt;br /&gt;
			$user_name = $row['user_name'];&lt;br /&gt;
&lt;br /&gt;
			// Create an array of items&lt;br /&gt;
			$items[] = $row['item_text'];&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		$stmt-&amp;gt;closeCursor(); // Free memory used in this query&lt;br /&gt;
&lt;br /&gt;
		// Output the user's name and identify what we're displaying&lt;br /&gt;
		echo "$user_name's Wish List&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;n";&lt;br /&gt;
&lt;br /&gt;
		// Loop through the items and output to the browser&lt;br /&gt;
		foreach($items as $item) {&lt;br /&gt;
			echo $item, "&amp;lt;br /&amp;gt;";&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;With the above query, we effectively &lt;em&gt;retrieve the user's name from the  &lt;tt&gt;users&lt;/tt&gt; table, then pull the list ID that matches the user's ID, and  finally retrieve all items that match the list ID&lt;/em&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The above script will output the following, assuming user ID 1 was passed:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;&lt;br /&gt;
Jason Lengstorf's Wish List&lt;br /&gt;
&lt;br /&gt;
F-Stop Maverick Bag&lt;br /&gt;
Bon Iver Tickets&lt;br /&gt;
Rogue Mocha Porter&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;By combining the queries using &lt;tt&gt;LEFT JOIN&lt;/tt&gt;, we create a much easier to  read snippet of code.&lt;/strong&gt; Also, by reducing the number of queries run, we can hope  to see faster execution in our scripts.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Like I said, I'm not a MySQL optimization expert, but from what I've read and  my limited testing, it seems pretty safe to say that &lt;strong&gt;using &lt;tt&gt;JOIN&lt;/tt&gt; to  reduce the number of queries in our scripts is a good way to not only enhance  the readability of our scripts, but also to grease them up for faster  execution.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Do you know any tricks for speeding up MySQL queries? How do you feel about  using &lt;tt&gt;JOIN&lt;/tt&gt; in queries? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2314%3A+Optimizing+MySQL+Queries"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uAr39u_GBQvvXh6XPpnf_EQ5q4I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uAr39u_GBQvvXh6XPpnf_EQ5q4I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uAr39u_GBQvvXh6XPpnf_EQ5q4I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uAr39u_GBQvvXh6XPpnf_EQ5q4I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/dcG5JBPyzz0" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/dcG5JBPyzz0/ITT+%2314%3A+Optimizing+MySQL+Queries</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2314%3A+Optimizing+MySQL+Queries</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2314%3A+Optimizing+MySQL+Queries</feedburner:origLink></item>
    <item>
      <title>ITT #13: Build a Menu with Recursive Functions</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1240956992_62610.jpg" alt="Because some visual clichès just never get old" /&gt;&lt;br /&gt;&lt;p&gt;To continue my &lt;a href="blog/tag/array"&gt;recent obsession with array handling&lt;/a&gt;, I want to spend this week talking about &lt;strong&gt;recursive functions&lt;/strong&gt; and their application in dealing with arrays.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The goal of our exercise today is to &lt;strong&gt;build a menu, complete with sub-menu&lt;/strong&gt;, all based off one function that runs recursively.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;What Is Recursion?&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In computer science, &lt;a href="http://en.wikipedia.org/wiki/Recursion_(computer_science)"&gt;recursion&lt;/a&gt; is a concept in which a &lt;strong&gt;function can call itself&lt;/strong&gt;. This is similar to the idea of looping in PHP, but it provides an opportunity, in the case of array handling, to add more fine-grain control into a program.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;On a basic level, recursion can be illustrated with the following code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function plusOne($x)&lt;br /&gt;
{&lt;br /&gt;
	if($x&amp;lt;10)&lt;br /&gt;
	{&lt;br /&gt;
		echo ++$x, "&amp;lt;br /&amp;gt;";&lt;br /&gt;
		plusOne($x);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		echo 'Finished! &amp;lt;br /&amp;gt;';&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Calling this function will result in the following output:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="html"&gt;1&lt;br /&gt;
2&lt;br /&gt;
3&lt;br /&gt;
4&lt;br /&gt;
5&lt;br /&gt;
6&lt;br /&gt;
7&lt;br /&gt;
8&lt;br /&gt;
9&lt;br /&gt;
10&lt;br /&gt;
Finished! &lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Obviously, the above could have been accomplished very simply with a loop, but it shows the basic idea behind recursion.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Constructing a Menu&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;In order to write our recursive array-handling function, let's first &lt;strong&gt;define the array&lt;/strong&gt; we'll be using. To build a menu, we'll need an &lt;em&gt;element for each menu item that contains information about each item&lt;/em&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Bear in mind that this example is very bare-bones, but should extend easily to include further information about your menu, including classes, IDs, or any other attributes you would want to add.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Basic Array Structure&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To start, let's build a very basic menu. We'll pretend we have a site that  needs &lt;em&gt;About Us, Blog, Links,&lt;/em&gt; and &lt;em&gt;Contact&lt;/em&gt; pages. To create this, our array might look like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
$menu = array(&lt;br /&gt;
	'about' =&amp;gt; array(&lt;br /&gt;
		'display' =&amp;gt; 'About Us'&lt;br /&gt;
	),&lt;br /&gt;
	'blog' =&amp;gt; array(&lt;br /&gt;
		'display' =&amp;gt; 'Read Our Blog'&lt;br /&gt;
	),&lt;br /&gt;
	'links' =&amp;gt; array(&lt;br /&gt;
		'display' =&amp;gt; 'Recommended Links'&lt;br /&gt;
		)&lt;br /&gt;
	),&lt;br /&gt;
	'contact' =&amp;gt; array(&lt;br /&gt;
		'display' =&amp;gt; 'Contact Us'&lt;br /&gt;
	)&lt;br /&gt;
);&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Above, we've given each menu item an array key that easily defines it, and in the case of this example, will serve as the item's URL unless it is otherwise defined.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Adding Sub-Menus&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Let's say that under our &lt;em&gt;Recommended Links&lt;/em&gt; item, we need to &lt;strong&gt;add a sub-menu&lt;/strong&gt; that holds links for a &lt;em&gt;Products&lt;/em&gt; and a &lt;em&gt;Services&lt;/em&gt; page. Additionally, the &lt;em&gt;Services&lt;/em&gt; page needs a sub-menu that leads the user to &lt;em&gt;Local&lt;/em&gt; and &lt;em&gt;Online&lt;/em&gt; services.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To accomplish this, we'll &lt;strong&gt;add another array element to our "links" element that contains an array&lt;/strong&gt; holding information about our sub-menus:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
	'links' =&amp;gt; array(&lt;br /&gt;
		'display' =&amp;gt; 'Recommended Links',&lt;br /&gt;
		'sub' =&amp;gt; array(&lt;br /&gt;
			'products' =&amp;gt; array(&lt;br /&gt;
				'display' =&amp;gt; 'High-Quality Products',&lt;br /&gt;
				'url' =&amp;gt; 'links/#products'&lt;br /&gt;
			),&lt;br /&gt;
			'services' =&amp;gt; array(&lt;br /&gt;
				'display' =&amp;gt; 'Helpful Services',&lt;br /&gt;
				'url' =&amp;gt; 'links/#services',&lt;br /&gt;
				'sub' =&amp;gt; array(&lt;br /&gt;
					'local' =&amp;gt; array(&lt;br /&gt;
						'display' =&amp;gt; 'Local Services',&lt;br /&gt;
						'url' =&amp;gt; 'links/#services_local'&lt;br /&gt;
					),&lt;br /&gt;
					'online' =&amp;gt; array(&lt;br /&gt;
						'display' =&amp;gt; 'Online Services',&lt;br /&gt;
						'url' =&amp;gt; 'links/#services_online'&lt;br /&gt;
					)&lt;br /&gt;
				)&lt;br /&gt;
			)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Notice that we included an element called "sub" that holds an array with two elements: "products" and "services". Also, note that the "services" element  has a "sub" element as well, containing an array with two elements: "local" and "online".&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We've also added a "url" element to our sub-menu items. This is so that we can have more control over where the menu is sending our users.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Turning the Array into a Usable Menu&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;With our array created, we need to &lt;strong&gt;write a function that will crawl through the array and build HTML markup&lt;/strong&gt; based on the information supplied to it. To start,  we need to define our function, which we'll call &lt;tt&gt;buildMenu()&lt;/tt&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function buildMenu($menu_array, $is_sub=FALSE)&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
	 * If the supplied array is part of a sub-menu, add the&lt;br /&gt;
	 * sub-menu class instead of the menu ID for CSS styling&lt;br /&gt;
	 */&lt;br /&gt;
	$attr = (!$is_sub) ? ' id="menu"' : ' class="submenu"';&lt;br /&gt;
	$menu = "&amp;lt;ul$attr&amp;gt;n"; // Open the menu container&lt;br /&gt;
&lt;br /&gt;
	// Create menu HTML here...&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * Close the menu container and return the markup for output&lt;br /&gt;
	 */&lt;br /&gt;
	return $menu . "&amp;lt;/ul&amp;gt;n";&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;We'll be passing &lt;strong&gt;two parameters&lt;/strong&gt; to the function, &lt;tt&gt;$menu_array&lt;/tt&gt; and  &lt;tt&gt;$is_sub&lt;/tt&gt;. The first, obviously, is the array containing the array of menu items. The second is a flag that will let our function know if it is  creating a sub-menu. This flag is to allow us to add an attribute to the menu HTML for easier CSS styling.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Our function will return a string, &lt;tt&gt;$menu&lt;/tt&gt;, that will contain the HTML markup to display our menu. Since the standard convention for marking up menus is to use the &lt;tt&gt;&amp;lt;ul&amp;gt;&lt;/tt&gt; tag, that's what we'll be doing here.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Step 1: Loop Through the Elements&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;After checking the &lt;tt&gt;$is_sub&lt;/tt&gt; flag and determining whether or not we're dealing with a sub-menu, we can loop through our elements. &lt;strong&gt;Because we're  dealing with multi-dimensional arrays, we'll have to nest loops,&lt;/strong&gt; which sounds complex, but is actually pretty simple once you see it in action.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The way we'll be constructing our loops will follow a pattern like this: &lt;em&gt;for  each element in the array, run a loop to extract information out of the nested array&lt;/em&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;In theory, the code will look like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function buildMenu($menu_array, $is_sub=FALSE)&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
	 * If the supplied array is part of a sub-menu, add the&lt;br /&gt;
	 * sub-menu class instead of the menu ID for CSS styling&lt;br /&gt;
	 */&lt;br /&gt;
	$attr = (!$is_sub) ? ' id="menu"' : ' class="submenu"';&lt;br /&gt;
	$menu = "&amp;lt;ul$attr&amp;gt;n"; // Open the menu container&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * Loop through the array to extract element values&lt;br /&gt;
	 */&lt;br /&gt;
	foreach($menu_array as $id =&amp;gt; $properties) {&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Because each page element is another array, we&lt;br /&gt;
		 * need to loop again. This time, we save individual&lt;br /&gt;
		 * array elements as variables, using the array key&lt;br /&gt;
		 * as the variable name.&lt;br /&gt;
		 */&lt;br /&gt;
		foreach($properties as $key =&amp;gt; $val) {&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * If the array element contains another array,&lt;br /&gt;
			 * call the buildMenu() function recursively to&lt;br /&gt;
			 * build the sub-menu and store it in $sub&lt;br /&gt;
			 */&lt;br /&gt;
			&lt;br /&gt;
			// Code here (see Step 2)...&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Otherwise, set $sub to NULL and store the &lt;br /&gt;
			 * element's value in a variable&lt;br /&gt;
			 */&lt;br /&gt;
			&lt;br /&gt;
			// Code here (see Step 2)...&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * If no array element had the key 'url', set the &lt;br /&gt;
		 * $url variable equal to the containing element's ID&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Code here (see Step 3)...&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Use the created variables to output HTML&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Code here (see Step 3)...&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Destroy the variables to ensure they're reset &lt;br /&gt;
		 * on each iteration&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Code here (see Step 3)...&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * Close the menu container and return the markup for output&lt;br /&gt;
	 */&lt;br /&gt;
	return $menu . "&amp;lt;/ul&amp;gt;n";&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The comments above frame out the steps we need to take in order to loop through the array and generate our markup.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Step 2: Extracting Array Data&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Now that our loops are set up, we need to &lt;strong&gt;write the code that will process the array elements&lt;/strong&gt; as they are looped.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Our first step is to &lt;strong&gt;determine whether or not the value of the current element is an array&lt;/strong&gt;. If so, we want to call &lt;tt&gt;buildMenu()&lt;/tt&gt; again. The reason for  this is that by doing so, we &lt;em&gt;create another unordered list within our menu&lt;/em&gt; that we can store in a variable (&lt;tt&gt;$sub&lt;/tt&gt;) for output with the parent element's markup (thus generating valid XHTML markup).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;If the current element is not an array, we use a programming trick called &lt;a href="http://us3.php.net/manual/en/language.variables.variable.php"&gt;variable variables&lt;/a&gt; to &lt;strong&gt;dynamically name a variable with the element key &lt;/strong&gt;(i.e.  &lt;tt&gt;'display' =&amp;gt; 'About Us'&lt;/tt&gt; is processed as &lt;tt&gt;$display = 'About  Us';&lt;/tt&gt;).&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function buildMenu($menu_array, $is_sub=FALSE)&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
	 * If the supplied array is part of a sub-menu, add the&lt;br /&gt;
	 * sub-menu class instead of the menu ID for CSS styling&lt;br /&gt;
	 */&lt;br /&gt;
	$attr = (!$is_sub) ? ' id="menu"' : ' class="submenu"';&lt;br /&gt;
	$menu = "&amp;lt;ul$attr&amp;gt;n"; // Open the menu container&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * Loop through the array to extract element values&lt;br /&gt;
	 */&lt;br /&gt;
	foreach($menu_array as $id =&amp;gt; $properties) {&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Because each page element is another array, we&lt;br /&gt;
		 * need to loop again. This time, we save individual&lt;br /&gt;
		 * array elements as variables, using the array key&lt;br /&gt;
		 * as the variable name.&lt;br /&gt;
		 */&lt;br /&gt;
		foreach($properties as $key =&amp;gt; $val) {&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * If the array element contains another array,&lt;br /&gt;
			 * call the buildMenu() function recursively to&lt;br /&gt;
			 * build the sub-menu and store it in $sub&lt;br /&gt;
			 */&lt;br /&gt;
			if(is_array($val))&lt;br /&gt;
			{&lt;br /&gt;
				$sub = buildMenu($val, TRUE);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Otherwise, set $sub to NULL and store the &lt;br /&gt;
			 * element's value in a variable&lt;br /&gt;
			 */&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				$sub = NULL;&lt;br /&gt;
				$$key = $val;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * If no array element had the key 'url', set the &lt;br /&gt;
		 * $url variable equal to the containing element's ID&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Code here (see Step 3)...&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Use the created variables to output HTML&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Code here (see Step 3)...&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Destroy the variables to ensure they're reset &lt;br /&gt;
		 * on each iteration&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Code here (see Step 3)...&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/*&lt;br /&gt;
	 * Close the menu container and return the markup for output&lt;br /&gt;
	 */&lt;br /&gt;
	return $menu . "&amp;lt;/ul&amp;gt;n";&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Step 3: Generate HTML and Clean Up&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Our final step is to &lt;strong&gt;use the information we've extracted&lt;/strong&gt; to generate our markup.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To start, we need to verify that a URL was supplied, and if not, substitute the top-most element's key as the URL. This provides a shortcut for menu items that don't need fancy URLs (i.e. &lt;a href="#"&gt;http://example.com/about/&lt;/a&gt;) by  allowing us to omit redundant information.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To accomplish this, we simply &lt;strong&gt;check that a variable was created&lt;/strong&gt; called  &lt;tt&gt;$url&lt;/tt&gt;, and if not, we create it and set it to the value of &lt;tt&gt;$id&lt;/tt&gt; that was extracted in our outermost loop.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;With our URL determined, we're ready to generate markup. This is a fairly  straightforward step, as we're just using the URL and display name extracted from our array to create an &lt;tt&gt;&amp;lt;li&amp;gt;&lt;/tt&gt; tag.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;With our menu item generated and added to the &lt;tt&gt;$menu&lt;/tt&gt; variable, we can safely unset the variables and start our next iteration of the outermost loop. Unsetting the variables prevents issues with the &lt;tt&gt;$url&lt;/tt&gt; variable storing the original default URL and breaking our menu.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The final function looks like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
	/*&lt;br /&gt;
	 * Loop through the array to extract element values&lt;br /&gt;
	 */&lt;br /&gt;
	foreach($menu_array as $id =&amp;gt; $properties) {&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Because each page element is another array, we&lt;br /&gt;
		 * need to loop again. This time, we save individual&lt;br /&gt;
		 * array elements as variables, using the array key&lt;br /&gt;
		 * as the variable name.&lt;br /&gt;
		 */&lt;br /&gt;
		foreach($properties as $key =&amp;gt; $val) {&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * If the array element contains another array,&lt;br /&gt;
			 * call the buildMenu() function recursively to&lt;br /&gt;
			 * build the sub-menu and store it in $sub&lt;br /&gt;
			 */&lt;br /&gt;
			if(is_array($val))&lt;br /&gt;
			{&lt;br /&gt;
				$sub = buildMenu($val, TRUE);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/*&lt;br /&gt;
			 * Otherwise, set $sub to NULL and store the &lt;br /&gt;
			 * element's value in a variable&lt;br /&gt;
			 */&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				$sub = NULL;&lt;br /&gt;
				$$key = $val;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * If no array element had the key 'url', set the &lt;br /&gt;
		 * $url variable equal to the containing element's ID&lt;br /&gt;
		 */&lt;br /&gt;
		if(!isset($url)) {&lt;br /&gt;
			$url = $id;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Use the created variables to output HTML&lt;br /&gt;
		 */&lt;br /&gt;
		$menu .= "&amp;lt;li&amp;gt;&amp;lt;a href="$url"&amp;gt;$display&amp;lt;/a&amp;gt;$sub&amp;lt;/li&amp;gt;n";&lt;br /&gt;
&lt;br /&gt;
		/*&lt;br /&gt;
		 * Destroy the variables to ensure they're reset &lt;br /&gt;
		 * on each iteration&lt;br /&gt;
		 */&lt;br /&gt;
		unset($url, $display, $sub);&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;The Generated Menu&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;When we run our function with the array we created earlier, we'll see the following output:&lt;/p&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;
&lt;ul id="sample_menu"&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="about"&gt;About Us&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="blog"&gt;Read Our Blog&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="links"&gt;Recommended Links&lt;/a&gt;&lt;br /&gt;
&lt;ul class="submenu"&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="links/#products"&gt;High-Quality Products&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="links/#services"&gt;Helpful Services&lt;/a&gt;&lt;br /&gt;
&lt;ul class="submenu"&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="links/#services_local"&gt;Local Services&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="links/#services_online"&gt;Online Services&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;a href="contact"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
&lt;p&gt;Our function was able to create a menu with two sub-levels (and it will go even deeper than that if necessary). The benefit of a function like this is that &lt;strong&gt;it  allows us to forego the annoying task of editing menu HTML for every new client&lt;/strong&gt; that we sign up, rather enabling us to &lt;em&gt;quickly define an array&lt;/em&gt; that will be parsed into HTML quickly and easily.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Recursive functions are a great way to overcome complex tasks, especially when  handling complex arrays such as our menu above. Taking a little time to get the hang of them can go a long way toward eliminating long strings of spaghetti  code that muddies up our scripts.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;How do you build your client menus? Do you have any clever ways to use  recursion? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2313%3A+Build+a+Menu+with+Recursive+Functions"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/er7-_og8GSYB6ZrKJeIxQTSuSqg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/er7-_og8GSYB6ZrKJeIxQTSuSqg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/er7-_og8GSYB6ZrKJeIxQTSuSqg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/er7-_og8GSYB6ZrKJeIxQTSuSqg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/9P_WqOn6Vmk" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/9P_WqOn6Vmk/ITT+%2313%3A+Build+a+Menu+with+Recursive+Functions</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2313%3A+Build+a+Menu+with+Recursive+Functions</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2313%3A+Build+a+Menu+with+Recursive+Functions</feedburner:origLink></item>
    <item>
      <title>ITT #12: Display Random Entries with PHP</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1240368107_58076.jpg" alt="A trick for dealing with array elements" /&gt;&lt;br /&gt;&lt;p&gt;I ran into an interesting problem while developing a new blogging system recently where I needed to &lt;strong&gt;generate a subset of array elements in  random order.&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;A random subset of elements is useful for displaying a sampling of entries that changes with every page load, such as four random blog entries, a photo gallery that stays interesting even if new photos aren't uploaded, or, if you want to use a  &lt;a href="http://www.brenelz.com/blog/2009/03/31/build-a-content-slider-with-jquery/"&gt;sweet  content slider&lt;/a&gt;, you could show random portfolio or blog entry previews and  keep your slider fresh.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Defining the Problem&lt;/h2&gt;&lt;br /&gt;
&lt;h3&gt;The Array&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;First things first, we need to know what we're dealing with. For the purpose of this example, we'll be using a &lt;strong&gt;multi-dimensional array&lt;/strong&gt; that  looks something like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
$entries = array(&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry One',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 8, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Two',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 9, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Three',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 10, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Four',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 11, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Five',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 12, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Six',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 13, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Seven',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 14, 2009'&lt;br /&gt;
	),&lt;br /&gt;
	array(&lt;br /&gt;
		'title' =&amp;gt; 'Entry Eight',&lt;br /&gt;
		'author' =&amp;gt; 'Jason Lengstorf',&lt;br /&gt;
		'date' =&amp;gt; 'April 15, 2009'&lt;br /&gt;
	)&lt;br /&gt;
);&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;This is an array that's similar to the kind that would be returned from a  database query. In it, we have eight entries, each of which contains another array that holds the title, author, and date of the entry (I omitted the entry itself in the interest of brevity).&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;The Goal&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Our goal is to &lt;strong&gt;create a subset of four entries in random order,&lt;/strong&gt; and to have the subset change every time the page is loaded (i.e. entries 4, 2,  8, and 7 are loaded the first time, then entries 3, 8, 1, and 6, and so on).&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Writing the Code&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Our array will be processed in a function called &lt;tt&gt;getRandomSubset()&lt;/tt&gt;, which will accept two arguments: the array (&lt;tt&gt;$entries&lt;/tt&gt;), and the number of entries to be returned in the subset (&lt;tt&gt;$number&lt;/tt&gt;).&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function getRandomSubset($entries, $number)&lt;br /&gt;
{&lt;br /&gt;
	// Process entries here...&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;PHP provides a ton of &lt;a href="http://us.php.net/manual/en/ref.array.php"&gt;array  handling functions&lt;/a&gt; that simplify the process of manipulating arrays. One of the available functions is called &lt;a href="http://us.php.net/manual/en/function.array-rand.php"&gt;&lt;tt&gt;array_rand()&lt;/tt&gt;&lt;/a&gt;, which returns a random assortment of array keys (as a variable if only one  element is returned, or as an array if two or more are returned).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We're able to pass two arguments to &lt;tt&gt;array_rand()&lt;/tt&gt;: the first is  required and contains the array from which we need random elements, and the  second is an optional specifier that allows us to decide how many elements need to be returned (if not set, this defaults to 1).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Because &lt;tt&gt;array_rand()&lt;/tt&gt; only returns the array element keys, we'll need to do a little more coding to get the actual element values. To do this, we'll create an empty array called &lt;tt&gt;$randList&lt;/tt&gt; that will store our random  array elements, then run a loop with the random keys to add each element to the array using another array function called  &lt;a href="http://us.php.net/manual/en/function.array-push.php"&gt;&lt;tt&gt;array_push()&lt;/tt&gt;&lt;/a&gt;, which adds a value to the end of an array.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function getRandomSubset($entries, $n)&lt;br /&gt;
{&lt;br /&gt;
	// Initiate the variable&lt;br /&gt;
	$randList = array();&lt;br /&gt;
&lt;br /&gt;
	// Pull the desired number of entry keys at random&lt;br /&gt;
	$keys = array_rand($entries, $n);&lt;br /&gt;
&lt;br /&gt;
	// Loop through the keys&lt;br /&gt;
	foreach($keys as $key) {&lt;br /&gt;
&lt;br /&gt;
		// Add the value to end of the return array&lt;br /&gt;
		array_push($randList, $entries[$key]);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return $randList;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To test this code, add the following snippet to a test page. &lt;em&gt;NOTE: The &lt;tt&gt;&amp;lt;pre&amp;gt;&lt;/tt&gt; tags are used to enhance the readability of output  generated by &lt;tt&gt;print_r()&lt;/tt&gt;.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
print_r(getRandomSubset($entries, 2));&lt;br /&gt;
echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Running the code will output something similar to the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;&lt;br /&gt;
Array&lt;br /&gt;
(&lt;br /&gt;
    [0] =&amp;gt; Array&lt;br /&gt;
        (&lt;br /&gt;
            [title] =&amp;gt; Entry Four&lt;br /&gt;
            [author] =&amp;gt; Jason Lengstorf&lt;br /&gt;
            [date] =&amp;gt; April 11, 2009&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
    [1] =&amp;gt; Array&lt;br /&gt;
        (&lt;br /&gt;
            [title] =&amp;gt; Entry Six&lt;br /&gt;
            [author] =&amp;gt; Jason Lengstorf&lt;br /&gt;
            [date] =&amp;gt; April 13, 2009&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
)&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;The Problem with Too Few Entries&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;One problem that exists in our code is that &lt;strong&gt;a warning will be issued and no values returned if more entries are requested than available in our entry  array.&lt;/strong&gt; If we call &lt;tt&gt;echo getRandomSubset($entries, 9);&lt;/tt&gt;, an error similar to the following will be output:&lt;/p&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;:  array_rand() [&lt;a href="http://us.php.net/manual/en/function.array-rand.php"&gt;function.array-rand&lt;/a&gt;]: Second argument has to be between 1 and the number of elements in the array in &lt;strong&gt;/Applications/xampp/xamppfiles/htdocs/test.php&lt;/strong&gt; on line &lt;strong&gt;75&lt;/strong&gt;&lt;br /&gt; &lt;br /&gt; &lt;strong&gt;Warning&lt;/strong&gt;:  Invalid argument supplied for foreach() in &lt;strong&gt;/Applications/xampp/xamppfiles/htdocs/test.php&lt;/strong&gt; on line &lt;strong&gt;78&lt;/strong&gt;&lt;br /&gt; Array ( )&lt;/p&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
&lt;h3&gt;Solving the Problem&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To correct this issue, we need to &lt;strong&gt;add a check that ensures the number of  entries requested does not exceed the number supplied.&lt;/strong&gt; If too many entries are requested, we then change the number of requested entries to match the number  of available entries, thus avoiding the error and outputting as many entries as possible.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
function getRandomSubset($entries, $n)&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
	 * If $n isn't greater than the number of entries,&lt;br /&gt;
	 * reset it to be the number of entries available.&lt;br /&gt;
	 */&lt;br /&gt;
	$n = (count($entries)&amp;lt;$n) ? count($entries) : $n;&lt;br /&gt;
&lt;br /&gt;
	// Initiate the variable&lt;br /&gt;
	$randList = array();&lt;br /&gt;
&lt;br /&gt;
	// Pull the desired number of entry keys at random&lt;br /&gt;
	$keys = array_rand($entries, $n);&lt;br /&gt;
&lt;br /&gt;
	// Loop through the keys&lt;br /&gt;
	foreach($keys as $key) {&lt;br /&gt;
&lt;br /&gt;
		// Add the value to end of the return array&lt;br /&gt;
		array_push($randList, $entries[$key]);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return $randList;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Testing the function should now &lt;strong&gt;always result in a subset of the  desired length with no duplicate entries.&lt;/strong&gt; The subset can then be  passed to the formatting function of your choice to handle formatting.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Getting comfortable with the intricacies of loops and arrays can have a huge  impact on the cleanliness and readability of your code. What tricks do you have up your sleeve? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Other Notes&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;For anyone who hasn't seen it yet, I've decided to try and monetize my blog  with the help of &lt;a href="http://buysellads.com/buy/detail/4684/"&gt;BuySellAds.com&lt;/a&gt;.  &lt;strong&gt;There are four banner ad spaces available, and they're  &lt;em&gt;cheap!&lt;/em&gt;&lt;/strong&gt; Click on the "Advertise Here" boxes in the upper-left  of this site to get your ad up today!&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I had an article run on NETTUTS called  &lt;a href="http://net.tutsplus.com/tutorials/php/add-power-to-your-php-with-multi-tiered-applications/"&gt;Add  Power to Your PHP With Multi-Tiered Applications&lt;/a&gt;. It covers what I consider to be best practices while writing code, so I'd love to hear your thoughts on it.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I'm still looking for guest bloggers on Ennui Design, so if you've got an idea, &lt;a href="mailto:answers@ennuidesign.com"&gt;email me&lt;/a&gt; and we'll talk about it.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Also, just as a general note, thanks for reading! I really appreciate your  comments and support, and I hope to keep supplying you with all the PHP geekery you can handle!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2312%3A+Display+Random+Entries+with+PHP"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/p6cZxPF548DKwmyqJfRyrLFCRIA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/p6cZxPF548DKwmyqJfRyrLFCRIA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/p6cZxPF548DKwmyqJfRyrLFCRIA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/p6cZxPF548DKwmyqJfRyrLFCRIA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/yI-ykPxpUlI" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/yI-ykPxpUlI/ITT+%2312%3A+Display+Random+Entries+with+PHP</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2312%3A+Display+Random+Entries+with+PHP</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2312%3A+Display+Random+Entries+with+PHP</feedburner:origLink></item>
    <item>
      <title>ITT #11: A Tip for Using Arrays</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1239754984_57077.jpg" alt="How do you illustrate an array?" /&gt;&lt;br /&gt;&lt;p&gt;This week's &lt;em&gt;Instant Tip Tuesday&lt;/em&gt; is a short one because I'm under some pretty tight deadlines. I'm still looking for developers to help out by guest blogging on Ennui Design, so  &lt;a href="mailto:answers@ennuidesign.com"&gt;contact me&lt;/a&gt; if you'd like to show your developing chops!&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;On a quick vanity note, &lt;a href="http://twitter.com/chadengle"&gt;Chad Engle&lt;/a&gt; did &lt;a href="http://dcth.info/?p=46"&gt;an interview with me&lt;/a&gt; over on the DCTH site, so head over there and check that out!&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Manipulate Arrays to Handle the First Element Differently&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Arrays, though they're incredibly useful, can also easily become confusing. This is especially true when dealing with multi-dimensional arrays, like a  collection of entries from a database (a blog, for instance, would have at &lt;em&gt;least&lt;/em&gt; two dimensions in an array of entries: each blog is an array of the different pieces of the blog, such as title, author, post date, and the entry itself; each entry array would then be stored in another array to keep the entries together).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Though confusing at first, getting comfortable with arrays can make a huge impact on your effectiveness as a programmer. Today, we're going to look at using  &lt;a href="http://us3.php.net/manual/en/function.array-shift.php"&gt;&lt;tt&gt;array_shift()&lt;/tt&gt;&lt;/a&gt; to simplify array-handling when displaying multiple entries from a database.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;The Ugly Way to Access the First Element&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Often times when I'm dealing with a result set on a page, I end up needing to perform a special function for the first result, then continue on with the rest of the data set. This led to some awkward code, looking something like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Loads the last 5 entries from the DB in an array with keys:&lt;br /&gt;
 *		'title'&lt;br /&gt;
 *		'author'&lt;br /&gt;
 *		'date'&lt;br /&gt;
 *		'entry'&lt;br /&gt;
 */&lt;br /&gt;
$entries = getEntriesFromDB($sql, 10);&lt;br /&gt;
&lt;br /&gt;
$html = "&lt;br /&gt;
	&amp;lt;h1&amp;gt; {$entries[0]['title']} &amp;lt;/h1&amp;gt;&lt;br /&gt;
	&amp;lt;span&amp;gt;Posted by {$entries[0]['author']} on {$entries[0]['date']}&amp;lt;/span&amp;gt;&lt;br /&gt;
	&amp;lt;p&amp;gt;{$entries[0]['entry']}&amp;lt;/p&amp;gt;";&lt;br /&gt;
&lt;br /&gt;
for($i=1, $n=count($entries); $i&amp;lt;$n; ++$i) {&lt;br /&gt;
	/*&lt;br /&gt;
	 * Creates a hyperlinked title&lt;br /&gt;
	 */&lt;br /&gt;
	$link = makeLinkedTitle($entries[$i]['title']);&lt;br /&gt;
&lt;br /&gt;
	$html .= "&amp;lt;h2&amp;gt;{$entries[$i]['date']} - $link&amp;lt;/h2&amp;gt;";&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo $html;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Note that I'm assuming the array returned from &lt;tt&gt;getEntriesFromDB()&lt;/tt&gt; is numerically indexed, which, logically, is how the array would be created when the information is loaded from the database. This means the &lt;tt&gt;$entries&lt;/tt&gt; array is indexed from &lt;tt&gt;$entries[0]&lt;/tt&gt; (first entry array) to  &lt;tt&gt;$entries[4]&lt;/tt&gt; (the last of five loaded entries).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This code outputs one article, then four recent headlines preceded by their  post dates. It looks something like this:&lt;/p&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;
&lt;h3&gt;Sample Entry Title&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Posted by Jason Lengstorf on April 14, 2009&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;This would be the actual entry, but for the sake of brevity, we'll pretend it was more of a Twitter post.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;April 10 - &lt;a href="#"&gt;&lt;strong&gt;Another Entry&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt; April 02 - &lt;a href="#"&gt;&lt;strong&gt;An Entry About Coffee&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt; March 28 - &lt;a href="#"&gt;&lt;strong&gt;This One's About Beer&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt; March 26 - &lt;a href="#"&gt;&lt;strong&gt;More of a Rant than an Entry&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
&lt;h2&gt;Optimizing the Code&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;By using &lt;tt&gt;array_shift()&lt;/tt&gt;, we can clean up the syntax a little bit and create a snippet of code that is much easier to scan in the future.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Loads the last 5 entries from the database&lt;br /&gt;
 */&lt;br /&gt;
$entries = getEntriesFromDB($sql);&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Removes the first array element and stores it in $first&lt;br /&gt;
 */&lt;br /&gt;
$first = array_shift($entries);&lt;br /&gt;
&lt;br /&gt;
$html = "&lt;br /&gt;
	&amp;lt;h1&amp;gt; $first[title] &amp;lt;/h1&amp;gt;&lt;br /&gt;
	&amp;lt;span&amp;gt; Posted by $first[author] on $first[date] &amp;lt;/span&amp;gt;&lt;br /&gt;
	&amp;lt;p&amp;gt; $first[entry] &amp;lt;/p&amp;gt;";&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Because the first element is no longer in the array, we can simplify&lt;br /&gt;
 * and use a foreach loop to move through the remaining entries&lt;br /&gt;
 */&lt;br /&gt;
foreach($entries as $e) {&lt;br /&gt;
	$link = makeLinkedTitle($e['title']);&lt;br /&gt;
	$html .= "&lt;br /&gt;
	&amp;lt;h2&amp;gt; $e[date] - $link &amp;lt;/h2&amp;gt;";&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo $html;&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The code above is much easier to read, which means future maintenance will be less painful.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Though it might not seem like much based on the example above, simplifying the handling of arrays can save hours of maintenance, especially when dealing with data sets that use arrays with ten, twenty, or even more elements per entry.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;How do you handle multi-dimensional arrays? What do you wish you could do  better with them? Let me know in the comments!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2311%3A+A+Tip+for+Using+Arrays"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pYQj58xXOuEIDVXvFv28BETJtDQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pYQj58xXOuEIDVXvFv28BETJtDQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pYQj58xXOuEIDVXvFv28BETJtDQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pYQj58xXOuEIDVXvFv28BETJtDQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/j_HhQUT4TpQ" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/j_HhQUT4TpQ/ITT+%2311%3A+A+Tip+for+Using+Arrays</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2311%3A+A+Tip+for+Using+Arrays</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2311%3A+A+Tip+for+Using+Arrays</feedburner:origLink></item>
    <item>
      <title>ITT #10: Understanding OOP</title>
      <description>&lt;img src="http://ennuidesign.com/img/userPics/1239136651_72407.jpg" alt="I left town without any art supplies, so I'm recycling art. Lame? Yeah." /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: &lt;a href="#cmnt102"&gt;This comment&lt;/a&gt; by Cal Evans pointed out an oversight on my part regarding naming conventions for classes. To avoid conflicting with other classes, names should be distinctive, and as such, I changed the name of the example class from "date" to "Ennui_Date".&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Recently, I've fielded a handful of questions concerning  &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming"&gt;object-oriented&lt;/a&gt; PHP. What is it? How does it work? Why should we care?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;I had similar questions when I first started looking at OOP. I mean, why the hell would I want to switch from the easy-to-understand procedural method?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href="http://us3.php.net/manual/en/language.oop5.php"&gt;Classes and objects&lt;/a&gt; might look confusing and difficult to manage at first, but they actually  significantly improve the organization and readability of your code if used  properly.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;A Practical Example&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Let's say, for instance, that we need to be able to get a formatted date string for various purposes throughout a site we're building. However, the format of  the date may vary throughout the site, and we may need to create a formatted  date from any given timestamp.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Additionally, we need to be able to add days to a date, in increments of one  week. Let's look at the difference between implementing a solution in both the procedural and object-oriented approaches.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Do What We Know: The Procedural Approach&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Our first step is to get a formatted date string. To do this, let's create a function that will accept a formatting string and a timestamp, both of which are optional. Then, inside that function, we check to see if a timestamp was supplied. If so, format for that date. Otherwise, return a formatted string for the current timestamp.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;We'll also define the &lt;tt&gt;addOneWeek()&lt;/tt&gt; function, but we'll get to how that works in a minute.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;function formatDate($format="F j, Y", $timestamp=NULL)&lt;br /&gt;
{&lt;br /&gt;
	if(isset($timestamp)) {&lt;br /&gt;
		return date($format, $timestamp);&lt;br /&gt;
	} else {&lt;br /&gt;
		return date($format);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function addOneWeek($timestamp=NULL)&lt;br /&gt;
{&lt;br /&gt;
	if(isset($timestamp)) {&lt;br /&gt;
		return $timestamp + 7*24*60*60;&lt;br /&gt;
	} else {&lt;br /&gt;
		return time() + 7*24*60*60;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;That's nice and easy. I know that when I call &lt;tt&gt;formatDate()&lt;/tt&gt;, I'm going to get a formatted date string. Nothing fancy, nothing confusing, right?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To call this function, we simply do the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;echo formatDate(); // Outputs today (e.g. 'April 7, 2009')&lt;br /&gt;
&lt;br /&gt;
echo formatDate('m-d-y', '1211756595'); // Outputs '05-25-08'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Trying Out the Object-Oriented Approach&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Now, just for fun, let's see how the &lt;em&gt;exact same functionality&lt;/em&gt; is  achieved with a class in PHP.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;class Ennui_Date {&lt;br /&gt;
	private $format;&lt;br /&gt;
	private $date;&lt;br /&gt;
&lt;br /&gt;
	function __construct($format=NULL, $date=NULL)&lt;br /&gt;
	{&lt;br /&gt;
		$this-&amp;gt;format = (isset($format)) ? $format : "F j, Y";&lt;br /&gt;
		$this-&amp;gt;date = (isset($date)) ? $date : time();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public function formatDate()&lt;br /&gt;
	{&lt;br /&gt;
		return date($this-&amp;gt;format, $this-&amp;gt;date);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public function setFormat($format)&lt;br /&gt;
	{&lt;br /&gt;
		if(isset($format)) {&lt;br /&gt;
			$this-&amp;gt;format = $format;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public function setDate($date)&lt;br /&gt;
	{&lt;br /&gt;
		if(isset($date)) {&lt;br /&gt;
			$this-&amp;gt;date = $date;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public function addOneWeek()&lt;br /&gt;
	{&lt;br /&gt;
		$this-&amp;gt;date += 7*24*60*60;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public function __toString()&lt;br /&gt;
	{&lt;br /&gt;
		return $this-&amp;gt;formatDate();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;But what does all of that mean?&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Understanding Classes and Objects in PHP&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;First and foremost, it's important to note that objects and classes, while closely related, are not the same thing. An object is any collection of stored information. In web applications, this could be data related to entries on a  page, users of the site, etc. By itself, this information isn't particularly  useful, which is why we need a class.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;A class acts a a blueprint for the object. It names the pieces of information  and provides methods for interacting with it.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Re-Examining Our Date Handler&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Let's look again at the class we've defined. We start by defining the class,  instantiating its variables, and declaring our constructor method:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;class Ennui_Date {&lt;br /&gt;
	private $format;&lt;br /&gt;
	private $date;&lt;br /&gt;
&lt;br /&gt;
	function __construct($format=NULL, $date=NULL)&lt;br /&gt;
	{&lt;br /&gt;
		$this-&amp;gt;format = (isset($format)) ? $format : "F j, Y";&lt;br /&gt;
		$this-&amp;gt;date = (isset($date)) ? $date : time();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;In this snippet, we've essentially said, "Create a class called 'Ennui_Date' that holds two pieces of information, a formatting string and a date timestamp. When when the class gets defined, check if a formatting string was passed, and set  it as the object's formatting string. Otherwise, use a default string. Then check if a date was passed, then store it as the object's date timestamp or use the current time."&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;The &lt;tt&gt;__construct()&lt;/tt&gt; function is a special function that PHP runs  whenever a new object is created. Well use it in this instance to allow us to pass our optional parameters to the object. The &lt;tt&gt;__construct()&lt;/tt&gt; function isn't required; it's just convenient.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;To format our date, we'll add a public method called &lt;tt&gt;formatDate()&lt;/tt&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;	public function formatDate()&lt;br /&gt;
	{&lt;br /&gt;
		return date($this-&amp;gt;format, $this-&amp;gt;date);&lt;br /&gt;
	}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Because we already checked our values in the &lt;tt&gt;__construct()&lt;/tt&gt; function,  we can simply return a formatted string based on the values stored in the  object.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;In order to simplify the display of our formatted date, we'll use another  special method, the &lt;tt&gt;__toString()&lt;/tt&gt; method. This method determines what happens if the object is used as a string (using the &lt;tt&gt;echo&lt;/tt&gt; construct, for instance). Because we already have a function to return the date, we simply need to reference it in the &lt;tt&gt;__toString()&lt;/tt&gt; method, like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;	public function __toString()&lt;br /&gt;
	{&lt;br /&gt;
		return $this-&amp;gt;formatDate();&lt;br /&gt;
	}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Now, to instantiate the object and output a formatted date, we use the  following code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;$date = new Ennui_Date();&lt;br /&gt;
echo $date; // Outputs today (e.g. 'April 7, 2009')&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Not exactly simple to set up, but how easy is it to ouput the date? But that seems like an awful lot of foundation just to output a formatted string.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;As we expand on our class, however, the convenience of OOP starts to become a  little more obvious.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Adding More Functionality&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;Let's say, for instance, we need to be able to change the date somewhere on the page we're building, and we don't want to use the default formatting string.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Procedural Approach&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;If we're thinking procedurally, we'd do it something like this:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;echo formatDate(); // Outputs today (e.g. 'April 7, 2009')&lt;br /&gt;
&lt;br /&gt;
$format2 = "l, F jS at g:iA";&lt;br /&gt;
$date2 = 1224981409;&lt;br /&gt;
echo formatDate($format, $date2); // Outputs 'Saturday, October 25th at 6:36PM'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;While there's nothing wrong with the approach above, it's feeling a little  messy.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Object-Oriented Approach&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;By declaring two new methods in our &lt;tt&gt;Ennui_Date&lt;/tt&gt; class, we can clean up the  code a little bit.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;	public function setFormat($format)&lt;br /&gt;
	{&lt;br /&gt;
		if(isset($format)) {&lt;br /&gt;
			$this-&amp;gt;format = $format;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public function setDate($date)&lt;br /&gt;
	{&lt;br /&gt;
		if(isset($date)) {&lt;br /&gt;
			$this-&amp;gt;date = $date;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;To implement the new methods, we simply use the following code:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;$date = new Ennui_Date();&lt;br /&gt;
echo $date; // Outputs today (e.g. 'April 7, 2009')&lt;br /&gt;
&lt;br /&gt;
$date-&amp;gt;setFormat('l, F jS at g:iA');&lt;br /&gt;
$date-&amp;gt;setDate(1224981409);&lt;br /&gt;
echo $date; // Outputs 'Saturday, October 25th at 6:36PM'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Because the variables are stored in the object, we don't have variables  floating around our code, which keeps the code more legible and  compartmentalized.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;Add a Week to the Date&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;By now, the benefits of OOP are starting to show, but it's still not too painful to use the procedural style. When we get into preprocessing our data, however, it starts becoming very obvious that OOP adds convenience to our code.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;addOneWeek(), Procedurally&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Let's add a week to our procedural implementation's date. We'll start by  defining our &lt;tt&gt;addOneWeek()&lt;/tt&gt; function:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;function addOneWeek($timestamp=NULL)&lt;br /&gt;
{&lt;br /&gt;
	if(isset($timestamp)) {&lt;br /&gt;
		return $timestamp + 7*24*60*60;&lt;br /&gt;
	} else {&lt;br /&gt;
		return time() + 7*24*60*60;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;The function accepts an optional paramter, a timestamp, and adds seven days' worth of time (7 days X 24 hours X 60 minutes X 60 seconds) and returns a new value: either seven days from the provided timestamp or seven days from now.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Running the function requires extra variables, like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;$format = 'm-d-y';&lt;br /&gt;
$time = 1211756595;&lt;br /&gt;
echo formatDate($format, $time); // Outputs '05-25-08'&lt;br /&gt;
&lt;br /&gt;
$newtime = addOneWeek($time);&lt;br /&gt;
echo formatDate($format, $newtime); // Outputs '06-01-08'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;It's starting to get a little tough to read. We haven't tied ourselves in a  knot by any means, but we now have two functions and three variables to keep organized in our minds.&lt;/p&gt;&lt;br /&gt;
&lt;h3&gt;Organizing with $this-&amp;gt;addOneWeek()&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;To help us stay organized, let's try to add a week with our &lt;tt&gt;Ennui_Date&lt;/tt&gt; class.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;	public function addOneWeek()&lt;br /&gt;
	{&lt;br /&gt;
		$this-&amp;gt;date += 7*24*60*60;&lt;br /&gt;
	}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Right off the bat, the method looks a little easier to swallow than its procedural counterpart. Its implementation is equally straightforward:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class="php"&gt;$date = new Ennui_Date();&lt;br /&gt;
echo $date; // Outputs today (e.g. 'April 7, 2009')&lt;br /&gt;
&lt;br /&gt;
$date-&amp;gt;addOneWeek();&lt;br /&gt;
echo $date; // Outputs a week from today (e.g. 'April 14, 2009')&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Here, we can clearly see how much cleaner OOP can be than procedural code. If  we start to imagine these implementations among other code that affects the web  app, it's easy to see how much easier it would be to track our &lt;tt&gt;Ennui_Date&lt;/tt&gt; object than our several variables and functions associated with our procedural attempt.&lt;/p&gt;&lt;br /&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;&lt;br /&gt;
&lt;p&gt;OOP is an incredibly powerful tool to have in your skill set, and it shouldn't  be overlooked as "too complicated" because, as we just discovered, classes and objects actually simplify programming after we take the time to get familiar  with them.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;It's also important to recognize that not everything needs to be object-oriented, and sometimes creating an object is overkill. However, if used tastefully, adding classes to your applications can greatly increase the  simplicity and portability of your code.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;Do you use classes and objects? How do you decide what should be a  class and what should remain procedural? Let me know in the comments!&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;(To read and post comments for this entry, visit &lt;a href="http://ennuidesign.com/blog/ITT+%2310%3A+Understanding+OOP"&gt;ennuidesign.com&lt;/a&gt;)&lt;hr /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rcNx1KbUqDKnZcUEWHhm3VU5VSc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rcNx1KbUqDKnZcUEWHhm3VU5VSc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rcNx1KbUqDKnZcUEWHhm3VU5VSc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rcNx1KbUqDKnZcUEWHhm3VU5VSc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/EnnuiDesign/~4/qKuB2qm6CA0" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/EnnuiDesign/~3/qKuB2qm6CA0/ITT+%2310%3A+Understanding+OOP</link>
      <guid isPermaLink="false">http://ennuidesign.com/blog/ITT+%2310%3A+Understanding+OOP</guid>
    <feedburner:origLink>http://ennuidesign.com/blog/ITT+%2310%3A+Understanding+OOP</feedburner:origLink></item>
  </channel>

</rss>
