<?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:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <description>PHP Advent</description>
    <title>PHP Advent</title>
    <link>http://phpadvent.org/</link>
    <pubDate>Fri, 10 Feb 2012 04:27:12 -0500</pubDate>
                <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/phpadvent" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="phpadvent" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
              <title>Facilitating Development Environment Consistency</title>
              <dc:creator>Jeff Loiselle</dc:creator>
              <description><![CDATA[<p>Every developer is different, but your team&#8217;s development environment does not have to be. A modern web app uses many different technologies. Common dependencies for a functioning web development environment include PHP and its necessary extensions, a web server, a database, testing frameworks, and other apps and services. The classic approach to assist a team of developers is to deploy a server and install all of the necessary packages one would need for development. This methodology provides a consistent environment for all of the developers on the team, therefore ensuring that all contributors receive the same experience throughout the development cycle. However, as consistent as a remote, homogeneous development might be, developing remotely introduces a number of problems, including speed sacrifices, and a nasty dependency on a reliable connection to the Internet. It is also difficult to tinker with experimental packages when you know it could affect the environment of everyone on your team.</p>

<p>Navigating a remote file system in order to find the file you want to edit can be cumbersome. Many text editors and IDEs have features that attempt to mitigate this pain, but I have never found one that works reliably and is comparable to the speed of local development. Saving a file over a network can introduce delay that adds up to a significant amount of lost productivity over time. File navigation aside, nothing beats the speed of working locally. In order to work on your local machine, you have to install all of the packages that the team is using, and each member has to do so as well. This approach introduces inconsistency. As developers, we seek consistency, speed, and, as much as we love the Internet, we would like to be able to work without it sometimes. So, what do we do? We build a machine within a machine that works on all platforms and ensures homogeneity across development environments.</p>

<p>Thanks to advances in virtualization technology and the open source community, a number of free tools exist that one can leverage to facilitate providing consistent virtual machines to your team.</p>

<h2>VirtualBox, Vagrant, and Puppet</h2>

<p>There are a few apps that are required in order to get started. <a href="http://virtualbox.org/">VirtualBox</a> is hardware virtualization software that allows you to run another operating system on your local machine. <a href="http://vagrantup.com/">Vagrant</a> is a set of scripts that allow you to easily manipulate those virtual machines from the command line. <a href="http://puppetlabs.com/">Puppet</a> allows you to define what configuration changes should be made to the machine to have it operate how you would like.</p>

<h3>Install VirtualBox</h3>

<p><a href="https://www.virtualbox.org/wiki/Downloads">Download</a> and install VirtualBox. You are now ready to install any operating system and run it locally.</p>

<h3>Install Vagrant</h3>

<p>Vagrant is a command line tool for building and distributing virtualized development environments with VirtualBox. Executing only a couple of commands, you can download and provision a virtual machine which matches that of your team.</p>

<p>Ruby and its package manager RubyGems are required to get going with Vagrant. There are <a href="http://vagrantup.com/docs/getting-started/index.html">detailed instructions by platform</a> to help.</p>

<p>Once Ruby and RubyGems are installed, execute the following command on your local machine to ensure that your packages are up-to-date.</p>

<pre><code>gem update --system</code></pre>

<p>To install Vagrant, issue the following command on your local machine:</p>

<pre><code>gem install vagrant</code></pre>

<h3>Configure Vagrant</h3>

<p>Assuming that everything has gone well, configuring Vagrant should be easy. I have created a sample <code>Vagrantfile</code> and base Puppet configuration in order to provision a machine with Apache, MySQL, PHP, MySQL, Xdebug, PEAR, PHP CodeSniffer, and PHPUnit. You can clone <a href="https://github.com/phishy/lamp-stack">my repository</a>.</p>

<p>Once you have cloned the sample repository, it is time to install the Vagrant base image. The following command will download the box via the Internet and cache it. It is a 300 MB download, but you should only have to do it once.</p>

<code>vagrant box add base http://files.vagrantup.com/lucid32.box</code>

<p>The next step is to modify your Vagrantfile. Its configuration will forward ports from your local machine to the VM, mount a local folder of your choice within your VM, and initialize Puppet as your default provisioner. I have already done this for you.</p>

<p>There are a couple important configuration directives in the Vagrantfile. Let&#8217;s take a look.</p>

<pre><code># This enables Puppet as the default provisioner
config.vm.provision :puppet

# For verbose output, and you wish to do a dry run, substitute this line
config.vm.provision :puppet, :options => "--verbose --debug"</code></pre>

<p>Once provisioning is complete, you will access the LAMP environment from your browser via <a href="http://localhost:8080/">http://localhost:8080/</a>. The following line is the magic that accomplishes this:</p>

<code>config.vm.forward_port "http", 80, 8080</code>

<p>Being that this entire exercise exists in order to work with local files that are served by the <abbr title="virtual machine">VM</abbr>, we will need to share a local directory to the machine. The following line mounts the folder named <code>www</code> in your home directory to Apache&#8217;s <code>DocumentRoot</code< (<code>/var/www</code>) on the virtual machine.</p>

<pre><code>config.vm.share_folder "www", "/var/www", "~/www"</code></pre>

<p>Whether you&#8217;ve elected to leave this configuration as-is or modify it, you can boot the virtual machine and begin provisioning it with the following command on your local machine. Make sure you are in the directory containing the <code>Vagrantfile</code>.</p>

<pre><code>vagrant up</code></pre>

<p>(If you get a stack dump and a permission error, an <a href="https://github.com/mitchellh/vagrant/issues/580">explanation</a> is available.)</p>

<p>Vagrant boots the base image with VirtualBox, then executes Puppet with the configuration located in <code>manifests/base.pp</code>. I have commented the lines in the <code>base.pp</code> file for you to better understand their function. Also, I have kept the configuration deliberately simple. More advanced configuration will require that you create modules that can be inherited, included, parameterized, &#38;c.</p>

<p>For reference, here is <a href="http://projects.puppetlabs.com/projects/puppet/wiki/Core_Types_Cheat_Sheet">more documentation on Puppet directives</a>.</p>

<p>Many developers have also written and shared Puppet scripts with the world. Here is a <a href="https://github.com/saz/puppet-php">more complicated LAMP setup</a>.</p>

<p>Once the machine is up and running, if you wish to SSH to the machine, you can do so like this:</p>

<pre><code>vagrant ssh</code></pre>

<p>In order to SSH to the machine without using Vagrant (for example, when creating a tunnel to use a GUI MySQL client), use the longer syntax:</p>

<pre><code>ssh vagrant@localhost -p 2222 (password: vagrant)</code></pre>

<p>There are very few reasons that you should have to configure the virtual machine from within itself. Connecting to the machine in this way should be limited to running environment-dependent command line tools such as PHPUnit and MySQL.</p>

<h2>Distributing and Provisioning with Puppet</h2>

<p>Puppet is the true hero here. Once a virtual machine is distributed, Puppet makes it easy to keep the configuration of machines synchronized. Think of your virtual machine as disposable. You should be able to destroy and recreate it without losing functionality. Any configuration changes that need to be made to the machine should be propagated to the Puppet configuration file and distributed via a Git repository or a Puppet server (puppetmaster). Remember, the key is for everyone to have the same environment, and to do that, no custom modifications should be made to the virtual machine without sharing your changes in configuration via the Puppet file.</p>

<p>If you have modified <code>base.pp</code>, you can easily reprovision the machine as follows:</p>

<pre><code>vagrant reload</code></pre>

<p>You can also completely destroy the machine and begin anew:</p>

<pre><code>vagrant destroy
vagrant up</code></pre>

<p>If you just want to suspend your virtual machine for later:</p>

<pre><code>vagrant suspend
vagrant resume</code></pre>

<p>Once you have configured a box, you can also package it up and distribute a binary version using Vagrant&#8217;s package command. I prefer creating a Git repository with many folders containing different configurations. For example, you could have a stable LAMP environment in one folder, and another containing a script to install the new PHP 5.4 release candidate. Yet another one could contain a Ruby or Python environment. Switching between them is as simple as suspending one machine and booting up another.</p>

<h2>Developing with a Consistent, Local Environment</h2>

<p>Now you should be able to easily modify files within your <code>www</code> directory on your local machine, reload your browser at <a href="http://localhost:8080/">http://localhost:8080/</a>, and see the results.</p>

<p>This configuration serves as a great development environment with which to begin. Each app will have its own set of dependencies. You can even distribute the configuration of the virtual machine within the app&#8217;s repository to serve as an explicit definition of the dependencies that it has. With this, you could configure your continuous integration server to deploy a machine, provision it, install the app, run its tests, and report back to you.</p>

<p>There is an ultimate level of configurability and flexibility with a setup like this. Above all, though, your team will now be able to work faster and more efficiently, and you won&#8217;t end up in a situation where something works differently in one environment from the next. I hope you find a way to use these tools for your own sanity.</p>

<h2>Developer Gift</h2>

<p>I can think of no better gift to give a developer than the <a href="http://ww.brookstone.com/phantom-ii-rc-helicopter">Phantom II RC helicopter</a>. When your codes get you down, and you just need to let off some steam, you can dive bomb your housemates or family members with this easily-manueverable craft. It&#8217;s reasonably durable and cheaper than other models&#8201;&#8212;&#8201;you can get two of them for $25.</p>]]></description>
              <link>http://phpadvent.org/2011/facilitating-development-environment-consistency-by-jeff-loiselle</link>
              <guid>http://phpadvent.org/2011/facilitating-development-environment-consistency-by-jeff-loiselle</guid>
              <pubDate>Sat, 24 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Look Ma! No Passwords!</title>
              <dc:creator>Dan Mills</dc:creator>
              <description><![CDATA[<p>Your user sign-in experience is one of the most important interactions on your site, and all of the options you have fall short of what you need. You can roll your own, but you already know how much that sucks. You can use a sign-in service, but it won&#8217;t have everything you want&#8201;&#8212;&#8201;easy to deploy, easy to use, no lock-in, and respects user privacy and choice.</p>

<h2>The BrowserID Solution</h2>

<p>You will be surprised at how easy it is to implement BrowserID. Are you ready? Check out our <a href="https://github.com/mozilla/browserid/wiki/How-to-Use-BrowserID-on-Your-Site">instructions</a>. Go on, I&#8217;ll wait right here.</p>

<p>Not bad, right? It&#8217;s super easy to use, too! Check out the <a href="https://browserid.org/about">user flow</a>. Did I mention that it works on Firefox, Chrome, Safari, Opera, and IE&#8201;&#8212;&#8201;even on iOS and Android?</p>

<p>You may have noticed that the flow is centered around choosing an email address to sign in with. That&#8217;s no accident. Email as a login identitier already makes sense to users and sites alike, which is no easy feat. Because email is inherently distributed, BrowserID can enable any email provider to act as an identity provider. For now, though, <a href="http://browserid.org/">browserid.org</a> verifies your email by sending you a message (a common pattern on the Web).</p>

<p>Of course, you want more than just an email, and in early 2012, the BrowserID team will start to add experimental features to get at least a name and an image. That&#8217;s just the tip of the iceberg. The goal is to enable rich APIs to the user&#8217;s identity.</p>

<h2>We Need You!</h2>

<p>The BrowserID team is very eager to get your feedback. Try it out on your own sites! Instead of coding it yourself, you can trivially add support via plugins on <a href="http://wordpress.org/extend/plugins/browserid/">WordPress</a> or <a href="http://drupal.org/project/browserid">Drupal</a>. You have no excuse; give it a whirl and let us know what you think on our <a href="https://lists.mozilla.org/listinfo/dev-identity">mailing list</a>. </p>

<p>We&#8217;re listening for your feedback. BrowserID is easy to implement directly, and it&#8217;s even easier to add support via plugins on WordPress or Drupal. Improve your users&#8217; sign-in experience; try out BrowserID, keep up with our <a href="http://identity.mozilla.com/">blog</a>, and let us know what you think.</p>

<p>The Web needs this. Let&#8217;s make it happen.</p>

<h2>Developer Gift</h2>

<p>I really like my <a href="http://www.sousvidesupreme.com/product.aspx?ProductID=30">SousVide Supreme Demi</a>. Sous vide cooking is really fun, and there&#8217;s a lot to try&#8201;&#8212;&#8201;highly recommended for anyone into food hacking.</p>

<p>I had a more <abbr title="do it yourself">DIY</abbr> sous vide setup before, but I switched to the SousVide Supreme Demi recently, and I like it better. It&#8217;s an all-in-one unit that looks good on the counter, so I can leave it out permanently without it looking like I&#8217;m running a science experiment.</p>

<p>You haven&#8217;t had scrambled eggs until you&#8217;ve had sous vide scrambled eggs. :-)</p>]]></description>
              <link>http://phpadvent.org/2011/look-ma-no-passwords-by-dan-mills</link>
              <guid>http://phpadvent.org/2011/look-ma-no-passwords-by-dan-mills</guid>
              <pubDate>Fri, 23 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Keep the Front in the Front</title>
              <dc:creator>Rachel Andrew</dc:creator>
              <description><![CDATA[<p>I&#8217;m both a front- and back-end developer, and, at <a href="http://edgeofmyseat.com/">edgeofmyseat.com</a>, we mainly work on projects where we get to control the full stack&#8201;&#8212;&#8201;from server configuration, through PHP and the database, to the front-end markup, CSS, and JavaScript. However, we also sometimes work on projects where we are developing the front end only, so we get to feel the pain of spending time carefully constructing semantic markup and optimized JavaScript to find the back end is filling it with additional HTML and adding inline styles that override our CSS.</p>

<p>On the flipside, our product <a href="http://grabaperch.com/">Perch</a> is a small content management system that aims to make it easy for non-developers to deploy a site. In this situation, we have to try and stay out of our customers&#8217; markup. In doing so, we&#8217;ve learned a lot about how to keep out of the front-end code while still enabling powerful functionality.</p>
		
<h2>Don&#8217;t Assume a Flavor of HTML</h2>

<p>Currently, people are using one of several flavors of markup. You might come across front-end developers using HTML4 (which allows unclosed tags, unquoted attributes, and upper or lowercase tags), XHTML (which requires a well-formed document, quoted attributes, closed tags, and must be lowercase), and, increasingly, HTML5 (which can be written HTML or XML style).</p>

<p>This variety of markup means that if your PHP is outputting any markup, it may well invalidate the documents created by the front-end developers. If they are good front-end developers, this is likely to irritate them. It will also make their job harder, as each time they validate a document, they will see the errors for the incorrect markup style, making it hard to see errors they may have introduced.</p>

<p>Quoted attributes are optional in HTML4 and HTML5 when written in an HTML manner. However, they are valid in HTML4, XHTML, and HTML5 (whichever way you code it). So, ensuring that you quote any attributes you must output (for example when displaying form elements) will mean they are valid for all DOCTYPES. Similarly, XHTML and XML require that elements are correctly nested and that tags are lowercase, and while these are not requirements for HTML, ensuring things are correctly nested, tags are lowercase, and that the document is &#8220;well formed&#8221; will be valid across all flavors.</p>

<p>That really just leaves the thorny issue of self-closing elements. Elements that have a separate closing tag&#8201;&#8212;&#8201;for example paragraphs or list items&#8201;&#8212;&#8201;are optionally closed in HTML DOCTYPES, but closing them is valid across all flavors. However, self-closing elements (for example, images &#60;img&#62; and line breaks &#60;br&#62;) are invalid in HTML if they have the closing forward slash, and invalid in XHTML without. If you need to output these elements, which include input elements for forms as well as images, you should ideally allow the front-end developers to set their preference as to which they use.</p>

<p>In Perch, we have a number of options that can be set by the designer implementing the CMS. These include whether tags should be closed and using HTML5 so we can utilize the new HTML5 form elements if that is the case. We can then safely output form elements using the correct syntax from our templating engine.</p>

<h2>Output Single Elements Only</h2>

<p>Even when using a templating engine, there are times when you might have to output some markup. If this is the case, a good rule to follow is that you should only output a single element at a time. This lets the front-end developers wrap that markup in some other element if needed. For example, if you are generating a list and need to output the <code>li</code> elements, avoid also outputting the list itself. Find a way to let the front-end developer decide whether this should be an ordered or unordered list.</p>

<h2>Avoid Inline Styles</h2>

<p>Try to avoid the temptation to output any inline CSS. Due to the rules of the cascade, inline styles take precedence over those set in the stylesheet, therefore your styles will overwrite those created by the front-end developer. This will displease them greatly, and it also means they need to contact you to get those inline styles changed should the need arise. If you need to add something to show that a particular item is distinct from others, it would be preferable that you added a class to the element and tell the front-end developer what that is and in which circumstance it will appear. That way the front-end developer keeps control over how the element looks.</p>

<h2>Allow HTML Class Attributes to Be Passed</h2>

<p>If you need to generate markup such as an image element, let the front-end developer pass a string that will be added to the element as an HTML class attribute. This helps them add their required CSS without needing to add additional markup around the element and putting a class on that.</p>

<h2>Use Familiar Syntax for Templating</h2>

<p>Many web designers and front-end developers are unfamiliar with PHP, so when implementing any kind of templating that will be used by non-PHP developers, it can make all the difference to use a syntax that will seem friendly and familiar to them.</p>

<p>We do this in Perch by using XML tags within our templates. For our designer customers&#8201;&#8212;&#8201;many who have never installed a CMS before&#8201;&#8212;&#8201;these tags and attributes look like something they understand. To see how use of familiar syntax can promote use of a system you need only look at jQuery, which has become the JavaScript library of choice for so many designers due to its use of CSS selectors to target elements in the DOM. A familiar syntax goes a long way toward helping front-end developers and designers feel confident that they can work with the back end without breaking anything.</p>

<h2>Let Front-End Developers Control Their Area of Expertise</h2>

<p>Good front-end developers will be as concerned about the performance of their code as you are about the back end. For performance reasons, it is seen as good practice to <a href="http://developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_5/">include JavaScript at the bottom of the page</a> rather than at the top. Ensuring that the developers have control over this sort of thing means they can place them there, if appropriate.</p>

<p>By handing control of the front-end development to front-end developers, you allow them to do their job to the best of their ability, unhampered by things appearing in their markup that they were not expecting. You also shift responsibility for that area of the site to them. If you generate reams of markup via PHP, then any time it needs to be changed, or if there is a problem with validation or any CSS issues, the request will come back to you.</p>

<h2>Developer Gift</h2>

<p>I don&#8217;t wear a lot of jewelry. However, I would definitely make an exception for the <a href="http://www.adafruit.com/products/440">iNecklace</a>:</p>

<blockquote><p>&#8220;Sophisticated. Elegant. Open Source. The iNecklace is a gorgeously machined aluminum pendant with a subtle pulsating LED.&#8221;</p></blockquote>

<p>There are also <a href="http://www.adafruit.com/products/379">iCufflinks</a>, if you are not the necklace wearing type.</p>]]></description>
              <link>http://phpadvent.org/2011/keep-the-front-in-the-front-by-rachel-andrew</link>
              <guid>http://phpadvent.org/2011/keep-the-front-in-the-front-by-rachel-andrew</guid>
              <pubDate>Thu, 22 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Social-Driven Development</title>
              <dc:creator>Chris Cornutt</dc:creator>
              <description><![CDATA[<p>As any developer can tell you, the way we write apps has changed dramatically over the past year. It&#8217;s been amazing to see how the quality of code being written has changed, too. Developers are no longer isolated creatures&#8201;&#8212;&#8201;code sharing has become a standard practice. Developers write helpful tools or apps and immediately want to share them with the world. They write blog posts and include a link to a <a href="http://github.com/">GitHub</a> repo with the latest changes. Projects are extended and improved and developers&#8217; eyes are opened with new techniques they hadn&#8217;t even thought of. This is social development at its best&#8201;&#8212;&#8201;the sharing of ideas and code to create an even broader community driven by the want for something better.</p>

<p>It wasn&#8217;t so long ago that a closed development process was the norm. You offered up a finished product to the world, and people either liked it or moved on to the next. Users might send in some feature requests, but whether they&#8217;d end up in the next release was anybody&#8217;s guess. Projects were developed by a certain group, and it was up to them if they wanted to listen to the feedback from their users.</p>

<p>Then came <em>social coding</em>. Developers were given a new road to follow, one that opened up a whole new world of contribution and commmunity. Suddenly, apps became living, breathing things, begging to be shared. They reached out into the world, an extension of the developer, and asked to be accepted and improved. GitHub and its fellow code sharing sites made this revolution possible. They made sharing a few simple commands away and revolutionized the way development works.</p>

<p>I propose that 2011 be known as the <em>Year of Social Development</em>, a point in time where it has become so widely accepted to share code that there&#8217;s no excuse not to.</p>

<p>I won&#8217;t bore you with yet another introduction to GitHub, though; there are plenty of sites out there for that. Instead, I want to share just a few of the ways that you can use these same social development sites to give back to the projects you love.</p>

<p>First on the list is <em>code contributions</em>. This is, by far, the most powerful way you can give back to a project. GitHub and <a href="http://bitbucket.org/">Bitbucket</a> both call these pull requests&#8201;&#8212;&#8201;code improvements and commits created by another developer in an effort to make the project better. These can range from simple documentation changes to brand new features that have been on the TODO list for a long time. I highly encourage you to find a project that you love to use, see if they&#8217;ve opened up their source, and contribute back if you can. It&#8217;s a satisfying feeling seeing an acceptance message and seeing your commits included in future releases.</p>

<p>Next on the list is something that can make or break a project, it&#8217;s <em>docmentation</em>. Just now, I mentioned contributing to the documentation via a pull request. What I&#8217;m talking about now is a different sort of documentation, the kind found in manuals, example code, tutorials, and wikis. Find a piece of code that you don&#8217;t see a wiki page for and make it! If you found it useful enough to track down, chances are others will want to know about it, too.</p>

<p>Finally, if you don&#8217;t know enough about the project to contribute code, or there&#8217;s no way for you to update the documentation, there&#8217;s still a great way to give back&#8201;&#8212;&#8201;<em>submit bugs</em>. Too many developers find things that aren&#8217;t quite right and work around them. Next time you come across something like this, don&#8217;t code the other way; let the developers know there&#8217;s a problem. Unit testing and general usage will only reveal some bugs. Issues really show through in specific situations. Be sure to include as much detail as you can in the report; those make for happier debugging for the devs.</p>

<p>Even if you can&#8217;t contribute to a project via the code, documentation, or bug reporting, there&#8217;s always one more way you can offer support&#8201;&#8212;&#8201;send the developers a message letting them know how much you appreciate their hard work. Nothing feels better than someone halfway across the world telling you what you&#8217;ve made helped them.</p>

<p>Social development is here to stay. Get involved, contribute where you can, and maybe even start a project of your own!</p>

<h2>Developer Gift</h2>

<p>My developer gift suggestion is more for the up and coming geeks in your lives. I&#8217;m a huge fan of the stuff <a href="http://thinkgeek.com/">ThinkGeek</a> sells and they have some great stuff for the kiddos. If you haven&#8217;t picked a gift for this holiday season may I suggest <a href="http://www.thinkgeek.com/geek-kids/newborn-infant/bbae/">one of these bibs</a>, a <a href="http://www.thinkgeek.com/geek-kids/3-7-years/e515/">t-shirt like this</a> or maybe even <a href="http://www.thinkgeek.com/geek-kids/7-13-years/e824/">a ship of their own</a>.</p>
]]></description>
              <link>http://phpadvent.org/2011/social-driven-development-by-chris-cornutt</link>
              <guid>http://phpadvent.org/2011/social-driven-development-by-chris-cornutt</guid>
              <pubDate>Wed, 21 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Code for the Users, Not for the Spec</title>
              <dc:creator>Drew McLellan</dc:creator>
              <description><![CDATA[<p>I don&#8217;t know exactly when it was that I started to resent the people I was writing code for, but it was a sure sign that I was feeling burned out. For ten years, I&#8217;d been working as a <em>development resource</em> in design and marketing agencies, then at Yahoo, and finally within my own client-services company. At some point along the way, I&#8217;d lost touch with the people using the software I was creating&#8201;&#8212;&#8201;and it sucked.</p>

<p>One of the great joys of creating software is solving problems. Not just academically solving problems, but really fixing things for people. Making other people&#8217;s lives better by enabling them to achieve more with less. The satisfaction gained by having another human being pleased to be using what you&#8217;ve created is what makes it all worthwhile. If that feedback loop is broken, you end up releasing code into a void like a machine churning out functionality to spec.</p>

<p>One thing you quickly find when you&#8217;ve reduced your role simply to one of coding to spec is that your default position for any request is &#8220;no.&#8221; To keep the project on time, on budget, and to prevent treading water, you have to stand firm against what could be seen as unnecessary changes and stupid requests from users who don&#8217;t really know what they&#8217;re talking about. It&#8217;s tiring saying &#8220;no,&#8221; and resentment toward those asking the questions quickly builds up.</p>

<p>Before you know it, work is not fun like it used to be.</p>

<p>The solution is easy. Stop coding for the spec, and start coding for the users again.</p>

<h2>Functionality Is Not Enough</h2>

<p>I think we&#8217;ve probably all been in a situation where users ask for something that already exists. With our small <abbr title="content management system">CMS</abbr>, <a href="http://grabaperch.com/">Perch</a>, users often asked for the ability to reorder content items.</p>

<p>Now, of course, it was already perfectly possible to reorder items&#8201;&#8212;&#8201;there were options to set the content to order on any field, and in either direction. If the user needed an arbitrary order, they could add a new field, add a number to their items, and order by that. On paper, it was quite a powerful and flexible system.</p>

<p>Yet, users were still asking for a way to order content. The functionality was there, but users were either not finding it, not understanding it, or both. The spec was met, but the functionality was failing the users.</p>

<p>Remember, the spec is a bare <em>minimum</em> requirement. To do a really great job, it&#8217;s sometimes necessary to go beyond what the spec says and make something that really works for the people who have to use it.</p>

<h2>Accept When Users Are Having Trouble</h2>

<p>A big part of this is learning to accept when working code is broken. Sometimes the wet problems are the most difficult to solve, and as with all wet problems, the first step to solving them is admitting you have a problem. As a developer, it&#8217;s a really tough lesson to learn that a perfectly functioning, bug-free feature is broken if users don&#8217;t understand it.</p>

<p>What you&#8217;ve developed may meet the spec&#8217;s requirements enough to get sign-off, but we&#8217;re not working for the spec anymore. How do we go about getting user sign-off?</p>

<p>Sometimes the issue can be resolved with better user messaging, or by rethinking the interface, but other times you just have to accept that users are having trouble, and you need to go back to the drawing board&#8201;&#8212;&#8201;and that&#8217;s okay. If what&#8217;s there doesn&#8217;t work for users, then it doesn&#8217;t work.</p>
<p>My number one recommendation in this situation is to simply listen to your users. Ask them what they&#8217;re trying to achieve. Much like Henry Ford&#8217;s debated &#8220;faster horses&#8221; quote, your users may come up with the wrong solutions, but their core requirement can often been distilled from those solutions. So ask them, and then listen carefully to the answer.</p>

<h2>Really Great Developers Solve Problems</h2>

<p>I went back to the drawing board with my content ordering and implemented a JavaScript drag and drop reordering interface. The core of what my users were asking for was a quick way to set an arbitrary content order. I&#8217;m not one to throw masses of JavaScript at every problem, but in this case, it seemed that drag and drop was a good way to achieve that goal.</p>

<p>Now, users can pick up a bit of content and easily drop it where they want it. Is the end result any different to the functionality we provided before? Absolutely not, but the process of getting there is more closely aligned to how users want to use the software.</p>

<p>Not only does this mean they&#8217;re not bugging me with requests for features that exist, it means that they&#8217;re able to achieve more with the software.</p>

<h2>FAQs Are Bugs You Haven&#8217;t Fixed Yet</h2>

<p>We have a policy of having no frequently asked questions. If users are asking about something with regularity, then it means we&#8217;re either not explaining things clearly, or the product can be improved.</p>

<p>With Perch, users needs to add their site&#8217;s domain and corresponding license key before they can log in to a new installation. If they missed all the instructions and failed to do so, they were presented with the following message:</p>

<blockquote><p>&#8220;Sorry, your license key isn&#8217;t valid for this domain.&#8221;</p></blockquote>

<p>While accurate, this message very rarely resulted in the user taking the correct course of action to resolve the problem. What they&#8217;d actually do is raise a support ticket saying that they couldn&#8217;t log in.</p>

<p>One way of addressing this would be to add an <abbr title="Frequently Asked Questions">FAQ</abbr> to our site that explains what to do when encountering the message. That would be a bandage on the wound&#8201;&#8212;&#8201;it would stem the bleeding but not alleviate the pain. The real solution was much simpler. We changed the error message:</p>

<blockquote><p>&#8220;Sorry, your license key isn&#8217;t valid for this domain. Log into your Perch account and add the following as your live or testing domain: example.com&#8221;</p></blockquote>

<p>With <code>example.com</code> being the domain the installation is running at. Following this simple change, nobody asks us this question anymore. I&#8217;m sure plenty of people still miss the setup instructions and see the error, but it&#8217;s no longer a problem for them&#8201;&#8212;&#8201;they just make the change and carry on without incident.</p>

<p>The very worst thing you can do with frequently asked questions is make a list of them on your web site. Frequently asked questions are bugs, and the only satisfactory answer to them is to fix the problem so the questions don&#8217;t get asked again.</p>

<p>Being a developer isn&#8217;t about providing tools; it&#8217;s about solving problems. If we want to enjoy what we do, make awesome things, and not feel burned out, then we need to find ways to solve problems that work really well for users. If you make great software, users will appreciate your work and you&#8217;ll feel proud about what you&#8217;ve achieved. That sounds like a good recipe for being happy in your work to me.</p>

<h2>Developer Gift</h2>

<p>Did you ever program a robotic turtle back in the 80s? Remember the fun of having code on the screen translate to movements of a physical device on the floor? Drawing lines on a big sheet of paper only has limited appeal, but there&#8217;s a grown-up equivalent with an open source electronics kit from <a href="http://arduino.cc/">Arduino</a>. Give the gift of hardware hacking!</p>]]></description>
              <link>http://phpadvent.org/2011/code-for-the-users-not-for-the-spec-by-drew-mclellan</link>
              <guid>http://phpadvent.org/2011/code-for-the-users-not-for-the-spec-by-drew-mclellan</guid>
              <pubDate>Tue, 20 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Egomaniacal and Scalable Apps</title>
              <dc:creator>David Coallier</dc:creator>
              <description><![CDATA[<p>The rise of cloud computing over the past few years has been incredible. Unfortunately, many still do not see the interest or do not comprehend its importance.</p>

<p>This is not a post about cloud computing and its benefits, but rather a refresher about understanding some basic rules of scalability and how to get started with building scalable apps while keeping in mind that most people and companies have limited budgets.</p>

<p>The concept of <a href="http://en.wikipedia.org/wiki/Shared_nothing_architecture">shared-nothing architectures</a> is well known in the scalability community&#8201;&#8212;&#8201;if such a thing even exists&#8201;&#8212;&#8201;but it seems to be frequently forgotten when it comes to building web apps.</p>

<h2>Scalability</h2>

<p>Before we dive into scalability theory, a reminder is in order; fast apps and infrastructures don&#8217;t necessarily scale.</p>

<p>Although scalability is a complex and arduous concept to explain, the generally-accepted meaning for load scalability is the ability for a system to handle a growing amount of work in a capable manner. In other words, it&#8217;s the ability to handle more load by adding more computing power. Will you be able to handle more users if you add more servers to your cluster?</p>

<p>Load scalability is about the ability to adjust and adapt. As Darwin once said (or meant to say):</p>

<blockquote><p>&#8220;It is not the fastest web app that survives peaks and popularity; it is the one that is most adaptable to change.&#8221;</p></blockquote>

<h2>Share Nothing</h2>

<p>For years, the PHP world (most of it) was deploying to a single server that contained the web server, the databases, the uploaded files, the session files, &#38;c.</p>

<p>This outdated setup looks like this:</p>

<p><img src="/i/201119-01.png" /></p>

<p>This was fine until web sites started going down because of a mention on Digg or Slashdot (for those of you who remember Slashdot). Apps were fast, but they couldn&#8217;t surpass a certain threshold of users.</p>

<p>This is about the time the concept of <em>shared-nothing architectures</em> began to take hold. Infrastructures are now decoupled, and every component can be easily replaced. This improved setup looks like this:</p>

<p><img src="/i/201119-02.png" /></p>

<p>By sharing nothing, every server that powers your app becomes egomaniacal and does not care about the rest of the infrastructure. Like modular object-oriented code, parts of your infrastructure become independent. For instance, your web server should no longer save sessions in local files, because at any given point in time, the number of web servers can change.</p>

<p>A system that is tightly linked to its filesystem for file uploads, databases, sessions, &#38;c. is not scalable. Luckily, in the PHP world, we have quite a few tools to help us attain a high degree of selfishness.</p>

<h2>Sessions</h2>

<p>Storing sessions on a single filesystem means that when the system scales and adds or removes servers, some sessions will be lost. There are a few solutions to the problem.</p>

<h3>Memcached</h3>

<p>Memcached has been used for many years in the PHP world, and it is a great way to store objects and sessions across a cluster of servers. For an even more scalable Memcached infrastructure, I recommend <a href="http://www.couchbase.org/get/couchbase/current">Membase</a>, which is open source and provides elasticity as well as persistence for Memcached.</p>

<p>Once you set up your Memcached infrastructure (and the <a href="https://github.com/php-memcached-dev/php-memcached">PHP extension</a>), you simply modify your session handler to point to your Memcached server (or pool) as follows:</p>

<pre><code>&lt;?php
    ini_set('session.save_handler', 'memcached');
    ini_set('session.save_path', '1.2.3.4:11211');
</code></pre>

<p>Many people dislike using Memcached for session storage, because the data is ephemeral, so if your server dies, all of your sessions are going to disappear, and your users will be logged out.</p>

<p>Membase avoids this problem and is fully compliant with the Memcached protocol.</p>

<h3>Redis</h3>

<p>An alternative to distributing sessions persistently across clusters of computers is to use <a href="http://redis.io/">Redis</a> and the <a href="https://github.com/nicolasff/phpredis">Redis PHP extension</a>.</p>

<p>Redis is an advanced key-value store (<em>data structure server</em>) that can contain strings, hashes, lists, sets, and sorted sets. Redis can be naturally replicated, and, despite being an in-memory system, it can also fall back to storing data on disk.</p>

<p>After installing the aforementioned PHP extension, you have modify your session handler to use Redis:</p>

<pre><code>&lt;?php
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', '1.2.3.4:6379');
</code></pre>

<p>In the event where you want to use a cluster of Redis instances, you can specify multiple servers:</p>

<pre><code>&lt;?php
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://1.2.3.4:6379?weight=1, tcp://4.3.2.1:6379?weight=2');
</code></pre>

<h3>SessionHandler</h3>

<p>PHP 5.4 has a new class called <code>SessionHandler</code>. This new class lets you write a custom object-oriented session handler.</p>

<p>Saving your sessions to Memcached using <code>SessionHandler</code> would look something like this:</p>

<pre><code>&lt;?php
class MemSession extends SessionHandler {

    public function read($key) {
        return parent::read(sha1($key));
    }

    public function write($key, $value) {
        return parent::write(sha1($key), $value);
    }
}

ini_set('session.save_handler', 'memcached');
ini_set('session.save_path', '1.2.3.4:11211');
session_set_save_handler(new MemSession);
</code></pre>

<p>Of course, sessions can be, and often are, saved to a database. Using <code>SessionHandler</code>, it is now easier than ever to do so.</p>

<h2>Distributed, Redundant File Storage</h2>

<p>Another limitation of most traditional web apps is saving files to a local filesystem.</p>

<p>If an app scales by adding more servers, saving files to the filesystem has the same limitations as saving sessions to the filesystem. The presence of files will be inconsistent across nodes, and your users will be frustrated.</p>

<p>A solution to this problem is to use systems that are built to store, distribute, and replicate files across multiple regions. A good example is Amazon S3 which can be easily supported with <a href="http://framework.zend.com/manual/en/zend.service.amazon.s3.html">Zend_Service_Amazon_S3</a> or <a href="http://pear.php.net/Services_Amazon_S3">PEAR::Services_Amazon_S3</a>.</p>

<p>For Symfony2, I use a bundle I made named <a href="https://github.com/orchestra-io/symfony2-s3streambundle">symfony2-s3streambundle</a>. It lets you easily write logs and similar files directly to Amazon S3 using <a href="https://github.com/Seldaek/monolog">Monolog</a>.</p>

<p>Once the bundle is installed, and your Amazon S3 bucket is created, all you have to do is modify the <code>app/config/config_prod.yml</code> file to add the following:</p>

<pre><code>monolog:
    handlers:
        nested:
            type:  stream
            path:  s3://your-bucket/%kernel.environment%.log
            level: debug</code></pre>

<p>There are other ways to distribute files, such as building your own filesystem cluster using GlusterFS, NFS, or any other variant of a distributed and eventually consistent file-storage system. I usually recommend using Amazon S3, because it is fast, reliable, highly available, and widely supported.</p>

<h2>Conclusion</h2>

<p>With cloud computing becoming more standardized, and platforms such as <a href="http://orchestra.io/">Orchestra</a> providing scalable architectures at the click of a mouse, application architecture is becoming more important, while infrastructure architecture is becoming simpler and more reliable.</p>

<p>There are more things to ponder when building a truly scalable architecture, such as message queuing, database replication, automated backups, self-healing, elasticity, and locality. PHP has many extensions and tools to help your app scale.</p>

<p>On a related note, if you are unaware of the <a href="http://gearman.org/">Gearman</a> and <a href="http://zeromq.org/">ZeroMQ</a> projects, I recommend learning more about them and considering whether they might fit into your current or next project.</p>

<h2>Developer Gift</h2>

<p>Einstein once said, &#8220;God does not play dice with the world.&#8221; Unfortunately for him, he may have been a few years too early for the very cute <a href="http://glyphobet.net/store/dice/">mathematician&#8217;s dice</a>, and they might have changed his mind. These are a great gift for adults and children alike. Happy Christmas!</p>]]></description>
              <link>http://phpadvent.org/2011/egomaniacal-and-scalable-apps-by-david-coallier</link>
              <guid>http://phpadvent.org/2011/egomaniacal-and-scalable-apps-by-david-coallier</guid>
              <pubDate>Mon, 19 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Simplifying Commerce for Small Business</title>
              <dc:creator>Ben Ramsey</dc:creator>
              <description><![CDATA[<p>Selling has never been easy. There&#8217;s too much red tape. The simple act of you giving me currency in exchange for a good or service I provide is not so simple when you factor in sales tax, VAT, inventory, shipping, reporting income, and any number of other factors that require accounting and fulfillment to be a damned nightmare&#8201;&#8212;&#8201;and that&#8217;s just when you give me paper money! When dealing with online transactions and credit cards, it can be downright gruesome.</p>

<p>The early days of commerce on the Web were difficult, to say the least. If you wanted a comprehensive solution for your business, you needed a merchant account specifically for online transactions, and you needed to process transactions through a gateway that could connect to your merchant account. On top of that, you&#8217;d have to estimate sales tax and shipping rates, and handle fulfillment and inventory on your own.</p>

<p>Solutions are easier now for small businesses and the developers who work with them. Simple <abbr title="application programming interface">API</abbr>s exist for use at affordable rates to handle transaction processing, sales tax calculation, and fulfillment.</p>

<h2>Transact</h2>

<p>In the early days of the Web, if you rolled your own cart, you likely used services like <a href="http://authorize.net/">Authorize.Net</a> and VeriSign PayFlow Pro (now <a href="http://paypal.com/">PayPal</a>). For developers, these weren&#8217;t easy to integrate with. For small businesses, the online merchant account was a headache, and SSL certificates were expensive, so many opted to redirect their carts to a third party, where the transaction would take place and then redirect back to the business&#8217;s site. This did not provide a very good user experience.</p>

<p><a href="http://stripe.com/">Stripe</a> is a new service aimed at developers and focused on simplifying transactions and integrations, allowing you to focus on user experience. They have a simple API and do not require a merchant account or gateway. In a sense, they are the gateway. They provide all the features you&#8217;d expect, including storing credit card data, offering the ability to set up subscription payments, and paying out directly to your bank account, but there&#8217;s no hassle. You simply accept the data from your own forms and send it to them over SSL. (You still need your own SSL certificate, but those are much cheaper these days.)</p>

<h2>Calculate</h2>

<p>Many businesses choose to avoid the hassle of calculating sales tax on the front end, and bake it into the cost of the good or service, but this means there&#8217;s hassle on the accounting side at the end of the year. Your accountant must then determine where you have nexus (a fancy term for regions where you are required to collect sales tax), examine the shipping address of everyone who bought from you to see if they need to calculate sales tax, and, if needed, calculate the sales tax for that jurisdiction&#8201;&#8212;&#8201;or guess at it and (hopefully) overpay.</p>

<p><a href="http://speedtax.com/">SpeedTax</a> (recently acquired by <a href="http://cch.com/">CCH</a>) provides a service with an easy-to-use API to reduce and eliminate this hassle. You can set up your <abbr title="stock keeping unit">SKU</abbr>s within the SpeedTax system and categorize them so that SpeedTax will know how to calculate the sales tax according to each jurisdiction&#8217;s laws. Then, you specify where you have nexus. When you send a request to the SpeedTax API, you include the SKU and the shipping address of the customer. SpeedTax takes care of the rest and gives you back the appropriate sales tax that you should collect for that jurisdiction.</p>

<h2>Fulfill</h2>

<p>Fulfillment includes three different processes, none of which are easy for a small business to perform alone. The first is calculating shipping fees. This can be done online, but you have to make decisions about which provider to use (USPS, UPS, FedEx, DHL, &amp;c.) and integrate with their API (APIs if you choose multiple providers). The second is determining whether you have the inventory required to fulfill the order. The third is actually picking, packing, and shipping the product. Most small businesses do this on their own at first, but if you want to scale your business, you&#8217;ll need to outsource this, so you can focus on running your business instead of shipping your product.</p>

<p><a href="http://shipwire.com/">Shipwire</a> provides all three of these services. Their APIs calculate shipping rates for a variety of vendors (which you can provide to your users as options), and you can store inventory within their global warehouses, so you can query their APIs to determine whether you can actually fulfill an order, based on inventory available. Furthermore, since you store your product in Shipwire&#8217;s warehouses, they will pick, pack, and ship your product based on API calls you make to their system.</p>

<h2>Seize the Opportunity</h2>

<p>When you or your clients are out and about, either at trade shows and conventions or just through the course of normal, everyday life, accepting payments whenever and wherever the opportunity arises is important.</p>

<p><a href="http://squareup.com/">Square</a> provides a credit card reader and app for iOS and Android devices that allows you to swipe and accept credit cards virtually anywhere. They don&#8217;t provide any APIs, so they&#8217;re not an application integration tool, but if you have clients who need to accept payments online, then they likely to need to accept payments offline, so suggest this solution to improve their business. Square is similar to Stripe in that they don&#8217;t require a merchant account, and they deposit directly to your bank account. What&#8217;s best is that the card reader and app are free!</p>

<h2>Simplify</h2>

<p>I&#8217;d be amiss if I didn&#8217;t mention that your mileage may vary. Depending upon your transaction volume and customer base, you may need to consider <a href="https://pcisecuritystandards.org/">PCI</a> compliance or <a href="http://truste.com/">TRUSTe</a> certification, among other compliance and regulatory considerations.</p>

<p>These are also not the only options out there. There are many, many products and solutions; I have only picked one from each category I&#8217;ve identified as important. I think these are good for small businesses; they&#8217;re easy to integrate with, and they&#8217;re affordable. They will simplify things for you or your clients. You may want to consider other options, though. For example, PayPal, Amazon, and Google provide excellent transaction alternatives that many of your customers will trust and appreciate.</p>

<p>Finally, I don&#8217;t want to close without promoting a simple solution provided by one of my Nashville friends, <a href="http://twitter.com/lukestokes">Luke Stokes</a>. <a href="http://foxycart.com/">FoxyCart</a> aims to simplify the checkout process for small businesses by providing a secure (PCI and Safe Harbor compliant) and fully-customizable (CSS and HTML) cart experience, while eliminating the need to host or develop your own cart or maintain your own SSL certificates. They provide features such as coupon codes and shipping rates.</p>

<h2>Developer Gift</h2>

<p>It&#8217;s no secret that I love beer. The other night, Luke Stokes asked me what my favorite beer was. It&#8217;s no small task for me to answer this. I like malty, I like hoppy, and I like sour. I really love Yazoo <a href="http://beerstreetjournal.com/yazoo-fortuitous-debuts-this-week/">Fortuitous</a>, but it&#8217;s hard to find. So, for those who like malty beers, I recommend the gift of <a href="http://www.newbelgium.com/beer/detail.aspx?id=2776aec8-790e-4f38-a53e-8a42d914ab81">Clutch</a> from New Belgium, and for those who like hoppy beers, I recommend <a href="http://www.newbelgium.com/beer/detail.aspx?id=e5d60cce-6eea-4ef9-a300-0a46e8ce5123">Le Terroir</a>, also from New Belgium. Both are sour. Both are delicious.</p>]]></description>
              <link>http://phpadvent.org/2011/simplifying-commerce-for-small-business-by-ben-ramsey</link>
              <guid>http://phpadvent.org/2011/simplifying-commerce-for-small-business-by-ben-ramsey</guid>
              <pubDate>Sun, 18 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>PHP for All the Things</title>
              <dc:creator>Matt Graham</dc:creator>
              <description><![CDATA[<p>PHP was originally designed for web sites and is still widely thought of only as a programming language for the Web. But with the approaches below and a variety of useful <a href="http://pear.php.net/packages.php?catpid=5&#38;catname=Console">console libraries</a>, PHP works great for command line scripts, too.</p>

<p>At Etsy, we have a variety of command line utilities that are all written in PHP. Having our web site and command line utilities in the same language means easier mental context switches between the two environments.  It also lets us reuse web code from the command line, particularly for data access or asynchronous processing.</p>

<h2>Arguments</h2>

<p>Just like web pages, command line scripts usually do more interesting things
when they take arguments. The command line arguments can be accessed with the <code>$argc</code> and <code>$argv</code> globals. <code>$argc</code> contains the number of arguments, and <code>$argv</code> holds an array that contains each argument; <code>$argv[0]</code> is always the filename of the PHP script being executed.</p>

<p> For simple options, using <code>$argv</code> directly is easy enough. Consider using <a href="http://php.net/function.getopt"><code>getopt()</code></a> or <a href="http://code.google.com/p/tylerhall/source/browse/trunk/class.args.php">this <code>Args</code> class</a> if you want to allow more complex options and flags like: <code>./script -n -g --near 4 --orange rectangle</code></p>

<p>Command line scripts often have different memory requirements than web requests. If you find your script running out of memory, don&#8217;t hesitate to explicitly increase the memory limit: <code>ini_set('memory_limit', '256M'); </code></p>

<h2>`Backticks`</h2>

<p>The first handy scripting tool is the <a href="http://php.net/language.operators.execution">execution operator</a> known as backticks (<code>``</code>). As with shell scripting, backticks will execute a given command and return whatever was written to standard output.</p>

<p>One place where we make extensive use of backticks is in our <em>builda</em> script, which we use to compile CSS and JavaScript as part of our deployment process. Rather than using PHP functions to navigate files and directories, we get everything with one shell command, as in the following example.</p>

<pre><code>$files = explode("\n", trim(`find $js_dir -type f`));</pre></code>

<p>Note that the backticks expand variables like <code>$js_dir</code> just as with double quoted strings. Remember that any input from strangers should be escaped with <a href="http://php.net/escapeshellarg"> <code>escapeshellarg()</code></a> or <a href="http://php.net/escapeshellcmd"> <code>escapeshellcmd()</code></a> before sending it to the shell.</p>

<p><em>Builda</em> was originally written in &#8220;not-PHP&#8221; but stagnated, because not everyone at Etsy was comfortable enough with that language to jump in and scratch their own itch. Since being rewritten six months ago in PHP, which all engineers know from working with the web code, seven different engineers have contributed to making the tool better.</p>

<h2>Standard Error</h2>

<p><code>print</code> and <code>echo</code> are easy ways to write to stdout. But, sometimes, command line programs want to write to standard error. For quick writes to <code>stderr</code>, try the following:</p>

<pre><code>file_put_contents('php://stderr', "error message\n");</code></pre>

<p>Alternatively, you can open <code>stderr</code> like a file and write to it with the standard file functions.</p>

<pre><code>$err = fopen('php://stderr', 'w');
fwrite($err, "another error message\n");</code></pre>

<h2>Pipes</h2>

<p>In cases where you require more interactivity with child processes, <a href="http://php.net/proc_open"><code>proc_open()</code></a> is often the right tool. It launches a process and opens pipes so that the two processes can communicate with each other.</p>

<p>As an example for how you might use <code>proc_open</code>, consider the case of loading data into sharded databases. Originally, we had only three shards, and it was easy to manually run one script for each shard. As the number of shards grew, this became more time consuming, so we wrote another script for loading data to all the shards at once.</p>

<p>The new script is actually two scripts. First, the child process, <em>shard_load</em>, is very simple. It opens a connection to a single shard, reads input from <code>stdin</code> and inserts rows into the database. By breaking the job into two scripts, each task is kept simple and can be tested independently.</p>

<p><img src="/i/matt-graham-load_all_shards.png"/></p>

<p>The main script, <em>load_all_shards</em>, is equally simple. It just reads a stream of input from <code>stdin</code>, opens a child process for each shard, and pipes rows of input to the appropriate child process. The pipes opened by <code>proc_open</code> can be read from and written to with functions like <a href="http://php.net/fgets"><code>fgets()</code></a> and <a href="http://php.net/fwrite"><code>fwrite()</code></a>, just like any other file handle.</p>

<pre><code>do {
    $line = $fgets($stdin);
    list($shard_id,$row) = split("\t", $line, 2);
    fwrite($shards[$shard_id]->stdin, $row);
    $line = fgets($handle);
} while ($line);</code></pre>

<p>All that needs to be done is to connect them with <code>proc_open</code>:</p>

<pre><code>function openShard($shard, $tbl, $fields) {
    $desc = array(
            0 => array('pipe', 'r'),
            1 => array('pipe', 'w'),
        );
    $pipes = array();
    $cmd = "./shard_load $shard $tbl $fields";
    $proc = proc_open($cmd, $desc, $pipes);
    return new ShardProc($shard, $proc, $pipes);
}</code></pre>

<h2>PHP Ubiquity</h2>

<p>With easy access to the shell and interprocess communication with pipes, there&#8217;s no reason not to take advantage of existing engineering experience (and web code) and use PHP for utility and offline scripts as well.</p>

<h2>Developer Gift</h2>

<p>Have you ever looked at the inside of a hard drive? It&#8217;s round and very shiny and perfect for a clock face! Any of <a href="http://www.etsy.com/shop/TECOART?section_id=6573933">these clocks</a> would make a great gift for your friendly neighborhood software developer.</p>]]></description>
              <link>http://phpadvent.org/2011/php-for-all-the-things-by-matt-graham</link>
              <guid>http://phpadvent.org/2011/php-for-all-the-things-by-matt-graham</guid>
              <pubDate>Sat, 17 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Cracks in the Foundation</title>
              <dc:creator>Gwynne Raskind</dc:creator>
              <description><![CDATA[<p>PHP has been around for a long time, and it&#8217;s starting to show its age. From top to bottom, the language has creaky joints. I&#8217;ve decided to take a look at how things got to this point, and what can be (and is being) done about it. I start out pretty gloomy, but bear with me; I promise it gets better.</p>

<h2>In the Beginning, There Was Apache and CGI</h2>

<p>And there was much rejoicing.</p>

<p>In 1994, Rasmus Lerdorf created the &#8220;Personal Home Page Tools,&#8221; a set of CGI binaries written in C. These tools looked little-to-nothing like the PHP we know today. Embedded in HTML comments, and using a syntax bearing no resemblance to C, they still contribute one critical principle to modern PHP; it <em>just worked</em>.</p>

<p>PHP is a language of convenience. It was built with the idea that anyone could toss together a few lines of code and have a working CGI script, without having to worry about the server interface, the cryptic syntax of Perl, or the pitfalls of C. It&#8217;s a great idea, in theory, and for the most part, it&#8217;s worked very well in practice.</p>

<p>Unfortunately, nothing&#8217;s perfect&#8201;&#8212;&#8201;PHP included. Over time, PHP has suffered everything from security failures to bad design decisions. Some of these problems were avoidable, but others weren&#8217;t.</p>

<h2>Backward Compatibility Is a Female Dog</h2>

<p>Backward Compatibility (or <em>BC</em>) is the bane of every library and app writer in existence. It stifles improvements, holds back innovation, promotes unsafe practices, frustrates users, and slows development. PHP, being a language intended for beginners, suffers from it even more than most.</p>

<p>When BC is broken, apps break. Operating system vendors who shipped the new and improved version of PHP tend to come under fire for having a broken system, even though they did nothing wrong. More often, the writers of the apps are vilified for not providing working software, despite having done nothing but follow the manual.</p>

<p>Sometimes, the source of the problem is correctly identified, and the PHP developers are berated for trying to make a better language. No matter who takes the blame, though, one thing remains constant; users rarely understand anything other than &#8220;it&#8217;s broken!&#8221; They don&#8217;t care whether the new version is better. The old one worked. They want it to keep working. It&#8217;s a reasonable expectation.</p>

<p>Unfortunately, with a programming language, it&#8217;s often impossible to meet that expectation without sacrificing features, safety, or speed&#8201;&#8212;&#8201;usually more than one of these.</p>

<p>PHP 4.4 was released to fix a bug that caused memory corruption when references were misued. The fix changed the internal API, forcing every extension module to be rebuilt. Unfortunately, rebuilding extensions can be an arduous process in some environments. Some extensions don&#8217;t come with source code. Others are ancient, and code that managed to struggle along finally stops compiling cleanly. Vendors (such as those who provide various flavors of Linux) who ship packages have to rebuild and test not only PHP itself, but also every extension they ship before pushing to their repositories.</p>

<p>The results of all this are twofold. First, almost everyone holds off on updating to the new version to avoid the work and cost involved in fixing the problems that arise, leaving them all running a version with publically disclosed memory corruption bugs. Second, PHP itself is discouraged from making similar changes in the future, lest adoption of compatible fixes be slowed. It only gets worse when the change breaks <em>source</em> compatibility, forcing app writers to change their code even after the vendors catch up.</p>

<p>All of this is bad enough when the change is essential for whatever reason. It&#8217;s far worse when the compatibility break is the result of bad choices or poor planning.</p>

<h2>Innovations Are the Devil&#8217;s Playthings</h2>

<p>There are several examples in PHP&#8217;s history of changes that were made by well-meaning, forward-thinking developers who were trying to make PHP better, only to be shouted down because of the trouble it would cause to implement them, or, worse, to actually make the change and suffer the chaos that ensued, because they didn&#8217;t realize how far the effects would reach.</p>

<p>A recent example is a change in the behavior of the <code>is_a()</code> function between versions 5.3.6 and 5.3.7. <code>is_a()</code> used to allow a <code>string</code> parameter as its first argument; it was changed so that it would call the autoloader when passed a string referring to a class that doesn&#8217;t exist. The new behavior was technically correct and consistent with the <code>is_subclass_of()</code> function, but calling into the autoloader when it previously hadn&#8217;t caused a great deal of working code to break. Several PEAR packages started throwing exceptions from the autoloader due to supposedly missing classes. Fixing these packages required adding an extra <code>is_object()</code> check to every place <code>is_a()</code> was used.</p>

<p>Unfortunately, by the time the scope of the problem was realized, and a solution was agreed upon, a further version in the 5.3 series, 5.3.8, had been released, with the new behavior intact. To revert the behavior at that point would have created a whole new BC break and necessitated a second round of code changes. By the time the situation was settled with a patch to the 5.4 tree and a reversion in 5.3.9, a <abbr title="Common Vulnerabilities and Exposures">CVE</abbr> report had been entered for the new behavior, and several mailing list threads regarding poor testing coverage and lack of procedures for BC breakage had reached impressive length.</p>

<p>All of this could have been avoided if a unit test had caught the break, or a procedure regarding BC breaks had been in place to prevent the change. The original author of the change can&#8217;t be held responsible for fixing a bug and correcting inconsistent behavior, but in an environment where fixes and corrections can have such far-reaching consequences, blame tends to get assigned (that fortunately didn&#8217;t happen in this case), and people become less willing to fix things.</p>

<p>On a rather less excessive note, for a long time there have been complaints about the inconsistent naming of array functions. It would be quite nice if, for example, the <code>[uka][r]sort()</code> family of functions was instead named <code>array_[uka][r]sort()</code>, but while the new function names could be added, the old ones couldn&#8217;t be removed for a very long time&#8201;&#8212;&#8201;at least two major PHP versions. With that limitation in mind, it seems pointless to add the new names. So, the old ones just stay&#8201;&#8212;&#8201;the result of a design decision far in PHP&#8217;s past, reasonable at the time (shorter function names were easier to understand, remember, and use).</p>

<h2>When the Porpoises Ask the Few Survivors What Went Wrong</h2>

<p>If, in the past, someone had asked me what was wrong with PHP, I probably would have said something like &#8220;developer apathy.&#8221; In early 2009, I took the lead in moving PHP&#8217;s source code from the increasingly creaky CVS repo to a shiny new SVN repo. I found that individuals with specific knowledge, such as whether a particular module needed to be saved or not, were in plentiful supply, but it seemed to me as if there was a lack of people to help with the overall process.</p>

<p>Let history be my judge in that regard. It may have been that offers of help were made that I misunderstood or chose to ignore. If so, I apologize to all who made the effort and were rebuffed. I do, however, stand by my assertion of apathy as a problem; PHP 6&#8217;s failure is an equally good example.</p>

<p>Even if we accept that perception as valid, it&#8217;s certainly not so any longer. A great deal more is happening with PHP now at the end of 2011 than was going on in early 2009. If asked what the problem is today, I would say, &#8220;no design and no plan.&#8221;</p>

<p>PHP has always been an evolving, almost-organic language. It has been rewritten from the bottom up at least four times, with massive internal changes to the engine at least twice more. Through all these mutations, however, its external interface&#8201;&#8212;&#8201;the language itself&#8201;&#8212;&#8201;has remained quite similar for a long time. Nearly everything that can be pointed to as different between PHP 3 and PHP 5.4 is an addition or extension to the language, not a change in existing behavior. There are exceptions, such as the new object model, but by and large, a PHP coder looking at PHP 5 code will be able to make complete sense of PHP 3, and vice versa. All of these versions share one flaw: there is no single specification of the language!</p>

<p>External tokenizers have to be implemented by reading the Zend Engine&#8217;s <a href="http://re2c.sourceforge.net/">re2c</a> and <a href="http://www.gnu.org/s/bison/">Bison</a> input files. Reimplementations of PHP have to refer constantly to Zend&#8217;s implementation to understand the quirks of the engine. The behavior of the language is inconsistent, and it often feels clunky. In particular, expressions do not reduce recursively to values as one might expect. <code>(new SomeClass)->methodReturningClosureReturningArray()()[5]</code> causes a parse error, for example, though a similar construct in Objective-C, <code>[[[SomeClass alloc] init] methodReturningBlockReturningArray]()[5]</code> works fine.</p>

<p>There are a variety of reasons why this behavior is part of the PHP language, but they boil down to two major points. First, there is no specification that says how the language <em>should</em> work; there&#8217;s nothing to compare against and say, &#8220;this is wrong&#8221; or &#8220;this is wrong.&#8221; Second, fixing issues like these in a complete and lasting form would necessitate a parser rewrite, and that means reimplementing the entire language differently. &#8220;BC break&#8221; doesn&#8217;t even begin to cover it.</p>

<h2>I Can See Clearly Now</h2>

<p>I&#8217;ve gone on at quite some length about PHP&#8217;s problems. I&#8217;ve mentioned some solutions to those problems, but I haven&#8217;t said much about what&#8217;s actually happening. So, here&#8217;s the situation, and it&#8217;s not nearly so bad as I may have made it sound.</p>

<dl>
	<dt>BC breaks</dt>
	<dd>A <a href="https://wiki.php.net/rfc/releaseprocess">new release process</a> was adopted in June of 2011, clarifying the timeline for releases, including the proper times for changes which break BC. This has also put PHP on a track for more regular releases in general, which is a significant help for vendors who bundle PHP.</dd>

	<dt>Communication problems</dt>
	<dd>PHP has historically had trouble with no one outside the core team knowing what was happening. In the last several months, there has been considerably more communication with OS vendors and others affected by changes and the release timeline. Some of them came to us, but in other cases we went to them.</dd>

	<dt>Lack of specification and standardization</dt>
	<dd>The lack of a language specification remains a significant issue, but at the very least, awareness of the problem has increased. An initiative to document the language behavior in a format such as <a href="http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form">EBNF</a> has been suggested.</dd>

	<dt>Unit tests ignored and broken</dt>
	<dd>This particular problem, brought to the public eye by a major security bug in the 5.3.7 release which was caught&#8201;&#8212;&#8201;and ignored&#8201;&#8212;&#8201;by a unit test, was dealt with shortly thereafter. Since that time, a huge number of failing tests were fixed, and the release managers now pay a great deal more attention to the test suite.</dd>

	<dt>Apathy<dt>
	<dd>Developer apathy in the PHP community has largely disappeared. Participation and discussion are considerably improved from where they once were. Development is now active on the 5.4 branch, the development line that grew out of the PHP 6 effort, and it&#8217;s already in RC status as of this writing.</dd>

	<dt>Undocumented, confusing engine API</dt>
	<dd>Unfortunately, the cruft of the Zend Engine&#8217;s API remains a sticking point. The API is complicated, mostly undocumented, and completely unintuitive. <code>zval</code> reference management comes to mind. Efforts made to document the API have stalled time and again. The news isn&#8217;t all grim, though; <a href="https://wiki.php.net/rfc/php_native_interface">an RFC</a> is in discussion to completely separate the internal API and create a new, clean external API.</dd>

	<dt>Bit rot (old code and features holding back new things)</dt>
	<dd>The new release process eases this quite a bit; it&#8217;s now safe to say there will be a new version at some point which isn&#8217;t afraid to break BC. This follows from a simple and obvious fact: the people affected by BC breaks will now have warning that it will happen. Deprecation in point releases is a bad way to handle future changes. Giving the expectation of major changes at a defined point in the future is a good way, and that&#8217;s where PHP is headed.</dd>

	<dt>No Unicode</dt>
	<dd>The lack of Unicode support in PHP remains a serious problem, but at least we&#8217;re no longer nursing a dying animal (PHP 6) in the vain hopes of making it work when the entire surrounding situation has changed. This opens the door for new ideas on how to fix the issue. For more on PHP 6&#8217;s history, see <a href="http://www.slideshare.net/andreizm/the-good-the-bad-and-the-ugly-what-happened-to-unicode-and-php-6">this excellent set of slides by Andrei Zmievski</a>.</dd>
</dl>

<h2>A Little Nonsense Now and Then Is Relished by the Wisest Men</h2>

<p>It&#8217;s safe to say PHP still has a long way to go to be the shining beacon of light we&#8217;d all like to see in a language, but it has withstood the test of time better than any other language of its kind, and it sees daily use across millions of servers. Nothing that&#8217;s wrong with PHP or its development is unsolvable, and tremendous progress has been made in the last year. No matter how dark I may have sounded during some parts of this article, I&#8217;m proud to be a part of PHP, and I hope I&#8217;ll continue in the future.</p>

<h2>Developer Gift</h2>

<p>A gift I recommend for any developer is a copy of any comprehensive book on hardware architecture and operating system design, with <a href="http://www.amazon.com/Inside-Machine-Introduction-Microprocessors-Architecture/dp/1593271042/">Inside the Machine</a> and <a href="http://www.amazon.com/Operating-Systems-Design-Implementation-3rd/dp/0131429388/">Operating Systems Design and Implementation</a> being two excellent examples. I have long held the belief that any developer&#8217;s skills&#8201;&#8212;&#8201;whether they&#8217;re writing raw machine code or PHP or anything in between&#8201;&#8212;&#8201;can be improved by a clear and comprehensive understanding of the machines themselves.</p>]]></description>
              <link>http://phpadvent.org/2011/cracks-in-the-foundation-by-gwynne-raskind</link>
              <guid>http://phpadvent.org/2011/cracks-in-the-foundation-by-gwynne-raskind</guid>
              <pubDate>Fri, 16 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Cross-Origin Ajax with CORS</title>
              <dc:creator>David Walsh</dc:creator>
              <description><![CDATA[<p>There&#8217;s no doubt that Ajax is one of the most exciting, useful, and necessary web technologies available to front-end developers. Unfortunately, it&#8217;s also one of the most restrictive&#8201;&#8212;&#8201;especially when it comes to gathering content from other domains. Web developers are nothing if not persistent, so we&#8217;ve come up with a variety of ways to get around cross-origin restrictions, including <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a>, server-side proxies made with PHP, <code>ProxyPass</code> proxying, Flash transports, creative iFrame uses, and more. What many developers don&#8217;t know is that there&#8217;s a <abbr title="World Wide Web Consortium">W3C</abbr> specification called <a href="http://www.w3.org/TR/cors/">Cross-Origin Resource Sharing</a>, or <em>CORS</em>, which provides a standard for cross-origin Ajax requests with minimal hassle.</p>

<p>Since the Ajax API is different across browsers, and most developers use a JavaScript toolkit, examples within this post will use the MooTools JavaScript framework. CORS will work with any JavaScript framework, since the core philosophy and code is configured on the server, not the client side. Due to its popularity, Apache will be used in server-side configuration examples.</em></p>

<h2>Basic Ajax Requests</h2>

<p>Each of the JavaScript frameworks abstracts <code>XMLHttpRequest</code> objects (or in the case of Internet Explorer, <code>ActiveXObject</code> or <code>Microsoft.XMLHttp</code>) to make Ajax requests. These requests feature a URL and may contain extra headers, data, different request types (<code>GET</code>, <code>POST</code>, <code>PUT</code>, or <code>DELETE</code>), and much more. A basic Ajax request would look something like this:</p>

<pre><code>// Create a new Ajax request
var request = new Request.JSON({
	// The URL to get content from
	url: "/countries.json",
	// The success callback
	onSuccess: function(countries) {
		// Log out the content
		console.log("The countries are: ", countries);
	}
}).send(); // Send the request</code></pre>

<p>The URL within the request above is local; <code>countries.json</code> is located within the same origin. What if we try to get tweets from Twitter, though?</p>

<pre><code>// Create a new Ajax request
var request = new Request.JSON({
	// The URL to get content from
	url: "http://twitter.com/statuses/user_timeline/davidwalshblog.json",
	// The success callback
	onSuccess: function(tweets) {
		// Log out the content
		console.log("The tweets are: ", content);
	}
}).send(); // Send the request
</code></pre>

<p>The request to Twitter will fail because the request destination, <code>twitter.com</code>, is not the same as the origin. Each browser provides its own error message; Chrome will warn you with: <code>XMLHttpRequest cannot load http://twitter.com/statuses/user_timeline/davidwalshblog.json. Origin http://davidwalsh.name is not allowed by Access-Control-Allow-Origin.</code></p>

<p>In the case of Twitter, we could use a JSONP request instead, but the problem with JSONP is that the destination server must support it. Even if the destination supports JSONP, you cannot <code>POST</code> to the URL or send specified request headers. How do we fix this conundrum? CORS, of course.</p>

<h2>Implementing CORS</h2>

<p>CORS allows for cross-origin requests with little fuss. Since the destination server is the entity in control and &#8220;at risk,&#8221; it must be configured with the proper headers and security settings. A few of the key headers include:</p>

<dl>
    <dt><code>Access-Control-Allow-Origin</code></dt>
    <dd>A specific URI or <code>*</code> which identifies what domain(s) may make cross-origin requests to this (destination) server. (<code>*</code> is an undesirable configuration value, since it allows any and all origins to make requests to your server.)</dd>
    <dt><code>Access-Control-Allow-Methods</code></dt>
    <dd>A comma-separated list of allowed request methods.</dd>
    <dt><code>Access-Control-Allow-Headers</code></dt>
    <dd>A comma-separated list of allowed request headers.</dd>
</dl>

<p>Assuming that a web site is hosted on an Apache server, the virtual host could be configured as follows:</p>

<pre><code>&lt;VirtualHost *:80&gt;
	DocumentRoot "/path/to/website/root"
	ServerName domain.tld
	Header set Access-Control-Allow-Origin http://example.com
	Header set Access-Control-Allow-Methods POST,GET
	Header set Access-Control-Allow-Headers X-Authorization,X-Requested-With
&lt;/VirtualHost&gt;</code></pre>

<p>The configuration above only allows remote requests from <code>http://example.com</code>, the request type may only be <code>POST</code> or <code>GET</code>, and allowed headers are <code>X-Authorization</code> and <code>X-Requested-With</code>.</p>

<p>If you want to allow anyone to make Ajax requests to your domain and with any request type, you could opt for this configuration:</p>

<pre><code>&lt;VirtualHost *:80&gt;
	DocumentRoot "/path/to/website/root"
	ServerName domain.tld
	Header set Access-Control-Allow-Origin *
	Header set Access-Control-Allow-Methods POST,GET,DELETE,PUT,OPTIONS
	Header set Access-Control-Allow-Headers X-Authorization,X-Requested-With
&lt;/VirtualHost&gt;</code></pre>

<p>With the destination server configured, we can send cross-origin requests from wherever we want:</p>

<pre><code>// Create a new Ajax request
var request = new Request({
	// The URL to get content from
	url: "http://example.org/content.php",
	// The success callback
	onSuccess: function(content) {
		// Log out the content
		console.log("The content is: ", content); // Works!
	}
}).send(); // Send the request</code></pre>

<p>The big question is, &#8220;which browsers have implemented the CORS spec?&#8221; Most of them, actually. Firefox 3.5+, Safari 4+, Chrome 3+, and IE9+. IE8 doesn&#8217;t support standard CORS, but it does have an <code>XDomainRequest</code> object, and Opera has not yet implemented CORS. That current level of support does, however, make CORS a viable option for many web sites. If you manage a web service or simply want to tinker with Ajax strategies, keep CORS in mind; I have a suspicion that CORS will play a large role in the future of web development.</p>

<h2>Developer Gift</h2>

<p>I&#8217;m terrible when it comes to figuring out what other people want as a gift. One gift that never misses is a good bottle of wine or a hard-to-find beer. Sometimes, a smooth wine or hoppy beer fuels a great, late-night coding session. Other times, it helps me get away from the text editor and relax. One added benefit of choosing wine is that your spouse might more quickly forgive your all-night hacking sins. My favorite wines come from <a href="http://kj.com/">Kendall Jackson</a>.</p>]]></description>
              <link>http://phpadvent.org/2011/cross-origin-ajax-with-cors-by-david-walsh</link>
              <guid>http://phpadvent.org/2011/cross-origin-ajax-with-cors-by-david-walsh</guid>
              <pubDate>Thu, 15 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Nightmare Before (Last) Christmas</title>
              <dc:creator>Jeremy Kendall</dc:creator>
              <description><![CDATA[<p>A little over a year ago I was plunged into a nightmare world. I had accepted a new job as the lone PHP developer at a relatively small business, and when I finally got my hands on the code, I realized I&#8217;d gotten myself into a giant mess. While I&#8217;m happy at my job today, my first months were filled with disbelief, horror, anguish, doubt, and despair as I began to dig into the legacy codebase I had inherited.</p>

<p>Things were a little dicey those first few months. I&#8217;d seen really bad code before (I&#8217;ve written some truly awful code myself), but I&#8217;d never seen anything quite like what I was dealing with.</p>

<p>Rather than run away screaming, I decided I&#8217;d try to wrangle this code into shape, one tiny piece at a time. Here are a few of the things I&#8217;ve learned over the past year about dealing with legacy code.</p>

<h2>There&#8217;s a Difference Between Internal and External Quality</h2>

<p>I once heard Stefan Priebsch comment on the fact that there&#8217;s a difference between internal and external quality where web apps are concerned. That was an &#8220;Aha!&#8221; moment for me, and I&#8217;ve never forgotten it. As bad as the code at my new gig was (and in many cases still is), the apps worked, and most of the users were very happy with them. Where I wanted to rewrite every bit of every app (including all of the front end), I had to remember that most everyone at the company was pleased with the way things were. Sweeping changes would cause more problems than they would solve.</p>

<h2>Version Control</h2>

<p>One of my favorite stories to tell about my first week on the job was when I asked, &#8220;What version control system are we using?&#8221; I naively expected we were using Subversion or Git. To my shock and horror, the developer replied, &#8220;There&#8217;s only one developer; we don&#8217;t need version control.&#8221; As soon as I recovered from that, I installed Subversion and versioned every bit of code and configuration I could find.</p>

<h2>Organize</h2>

<p>Not only was the code itself a mess, its location and organization was such that it was nearly impossible to find the code I was supposed to be working on in the first place. The situation with the server config files was nearly as bad. I did two things that helped immensely:</p>

<ol>
	<li>I placed all of our sites in <code>/sites</code> and named each site&#8217;s directory after the site&#8217;s URL.</li>
	<li>I reorganized the existing Apache config files, breaking out the numerous <code>VirtualHost</code> directives into their own files.</li>
</ol>

<h2>Do. Not. Rewrite. Seriously, Don&#8217;t Do It.</h2>

<p>Rewriting should never be the first option. It shouldn&#8217;t be the second option, nor even the third. Previous developers have domain knowledge you don&#8217;t; they&#8217;ve solved bugs and addressed user issues you don&#8217;t know anything about. Unless the external quality of the app has degraded to the point a complete rewrite is necessary, the best thing to do is take it slow.</p>

<h2>Take It Slow</h2>

<p>Refactor the code <em>one little bit at a time.</em> When I say one little bit, I&#8217;m not joking. Tiny changes. Small things like <a href="http://phpadvent.org/2011/more-than-just-style-by-laura-beth-denker">instituting a coding standard</a> and reformatting the code you&#8217;re working on can work wonders for readability. You might change variable names to be more descriptive, or move functions closer to where they&#8217;re being called. At that point, and before you begin refactoring, it&#8217;s time to write tests.</p>

<h2>Tests Are Your Best Friend</h2>

<p>The code I found seemed to be untestable, but over time, I&#8217;ve discovered that there&#8217;s very little code that&#8217;s truly untestable, even if you have to go through contortions to test it. The orthodoxy of automated unit and integration testing is excellent in theory, and amazing when you can make it happen (it should be a number one goal), but sometimes the reality of your situation won&#8217;t allow for that. I frequently use the following technique when I begin testing disastrous code:</p>

<ol>
	<li>Make a small change.</li>
	<li>Refresh the browser.</li>
	<li>Rinse. Repeat.</li>
</ol>

<h2>Don&#8217;t Forget to Have Fun</h2>

<p>Derek Siver&#8217;s post, <a href="http://phpadvent.org/2011/because-its-fun-by-derek-sivers">Because It&#8217;s Fun!</a>, really resonated with me. I started programming for many different reasons, but one of them was that programming is fun. There&#8217;s nothing more exciting&#8201;&#8212;&#8201;nothing that makes me happier&#8201;&#8212;&#8201;than solving a really difficult programming problem. What bigger problem is there than a disastrous legacy codebase? When I stopped crying over how bad I had it and started laughing at what I found, I started enjoying my work again. Now, I find I enjoy coming to work and making something beautiful out of something bad. I hope you can, too.</p>

<h2>Developer Gift</h2>

<p>I&#8217;m a huge fan of gift certificates&#8201;&#8212;&#8201;<em>huge</em>&#8201;&#8212;&#8201;and I can&#8217;t think of a better place for a developer shopping spree than <a href="http://www.thinkgeek.com/brain/order/certificate.cgi">ThinkGeek</a>.</p>

]]></description>
              <link>http://phpadvent.org/2011/nightmare-before-last-christmas-by-jeremy-kendall</link>
              <guid>http://phpadvent.org/2011/nightmare-before-last-christmas-by-jeremy-kendall</guid>
              <pubDate>Wed, 14 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Don’t Forget the Front</title>
              <dc:creator>Beth Tucker Long</dc:creator>
              <description><![CDATA[<p>Everyone talks about automated testing for your code, but that&#8217;s only half of the testing I need. What about the front end? Forms need some testing love, too, and <a href="http://simpletest.org/">SimpleTest</a> is how I get it.</p>

<p>SimpleTest is very easy to install. Just <a href="http://simpletest.org/en/download.html">download the latest version</a>, upload it to your server, then unzip it. That&#8217;s it! Now you can get started writing tests.</p>

<p>SimpleTest can handle all of the unit testing for your normal behind-the-scenes code, but it also has an internal web browser, so it can also test the front end, too. To get started, create a PHP file for your tests. Include <code>autorun.php</code> from SimpleTest. For tests that will use the internal web browser, you also need to include <code>web_tester.php</code>. Then, create a class for your tests that extends the <code>WebTestCase</code> class.</p>

<pre><code>require_once 'simpleTestDir/autorun.php';
require_once 'simpleTestDir/web_tester.php';

class contactForm extends WebTestCase {

}</code></pre>

<p>It&#8217;s now time to get down to the actual tests. SimpleTest offers a lot of options for ways to test. You can check the page title, whether specific text is present on a certain page, whether a certain cookie exists, and so much more. See the <a href="http://simpletest.org/en/overview.html">SimpleTest documentation</a> for a complete list of options.</p>

<p>One of the things that I like to test is to make sure that a specific error message displays when bad data is sent in a form. With SimpleTest, this is easy. Load a form using <code>$this->get()</code> and provide the URL of the page you want to test. Enter data into a field using <code>$this->setField()</code> and provide the name of the field as the first argument and the value of the field as the second argument. Commit an error, such as leaving one of the required fields empty, then submit the form with <code>$this->clickSubmit()</code> and provide the title of the submit button. Finally, you can check that the error message is displaying on the resulting page by running <code>$this->assertText()</code> and providing the text of the error message. The code would look something like this:</p>

<pre><code>require_once 'simpleTestDir/autorun.php';
require_once 'simpleTestDir/web_tester.php';

class contactForm extends WebTestCase {
   function testUsernameField() {
      $this->assertTrue($this->get('http://myWebsite.com/myForm/'));
      $this->setField('username', 'bad username');
      $this->clickSubmit('Send');
      $this->assertText('Please enter a username with no spaces.');
   }
}</code></pre>

<p>Now, when you view your test file in a browser, you will get a report telling you your test case is complete and that&#8201;&#8212;&#8201;hopefully&#8201;&#8212;&#8201;you have two passes, one for your <code>assertTrue</code> and one for your <code>assertText</code>. You did it; you are testing your form! SimpleTest also integrates with many of the continuous integration platforms, so you can incorporate front-end testing into the rest of your testing toolbox.</p>

<h2>Developer Gift</h2>

<p>I have two gift suggestions.</p>

<p>What do you get for the developer who has everything? How about a motorcycle repair shop in Honduras? <a href="http://kiva.org/">Kiva</a> lets you become a microfinancer, lending money to small, locally-owned businesses around the world. Kiva handles everything for you and sends you updates on the status of your loans. It&#8217;s a great way to take a small amount of money and make a big difference in someone&#8217;s life.</p>

<p>Love to play guitar, but don&#8217;t want to deal with the bulk of carrying one around all the time? Get the <a href="http://www.thinkgeek.com/tshirts-apparel/interactive/c498/">Electronic Rock Guitar Shirt</a>! You can keep coding, but your guitar is ready for rocking at a moment&#8217;s notice. (And yes, it really plays!)</p>]]></description>
              <link>http://phpadvent.org/2011/dont-forget-the-front-by-beth-tucker-long</link>
              <guid>http://phpadvent.org/2011/dont-forget-the-front-by-beth-tucker-long</guid>
              <pubDate>Tue, 13 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Bake Cookies Like a Chef</title>
              <dc:creator>Michael Nitschinger</dc:creator>
              <description><![CDATA[<p>It&#8217;s Christmas time again. While you write the first lines of your shiny new authentication library, the smell of tasty cookies is slowly sneaking into your room. The few minutes until they are finished is a good time to lean back and think about cookies&#8201;&#8212;&#8201;not the ones in the kitchen, but the cookies in your browser.</p>

<p>Let&#8217;s explore how to securely store data on the client side, and how to detect unwanted modifications.</p>

<h2>Ingredients</h2>

<p>Nearly every web app needs some kind of authentication, and most use cookies to help with identity. Cookies are a very convenient, portable, and scalable method to identify users after they have been authenticated. Unfortunately, you have to store those cookies on the client. The phrase &#8220;all user input is evil&#8221; is often used when you have to deal with data from the client, so it is important to realize that cookies are under the client&#8217;s control.</p>

<p>The first thing to remember is that cookies can provide more information to the user that you might think. For example, if your cookie contains a <code>PHPSESSID</code> key, an attacker doesn&#8217;t need fancy attack tools to immediately recognize that your app probably uses PHP. Every bit of information is important for an attacker, even if it doesn&#8217;t <em>seem</em> important.</p>

<p>An example from the Microsoft world is if you see <code>ISAWPLB</code> in a cookie, chances are that the target app uses the ISA Server as a reverse proxy or load balancer. Just look at the cookies of apps that you use regularly, and Google for some of the keys. Attackers can use this information in ways you would never consider. If you don&#8217;t believe me, take a look at the presentation entitled <a href="http://www.youtube.com/watch?v=fEmO7wQKCMw">How I Met Your Girlfriend</a>, by Samy Kamkar, which was presented at DEFCON 18. He shows you how to reduce the entropy of PHP sessions from 160 bits to 20 bits, which is much easier to brute force.</p>

<p>Attackers may also use cookies to bypass your authentication mechanisms. For example, if you implement a &#8220;remember me&#8221; feature by storing the user ID in the cookie (and no additional checks are performed on the server side), then the attacker may randomly change the ID in the cookie until he finds a valid one. It&#8217;s not very hard to guess that admin users have low IDs, right? If you want to learn more about attack vectors like this, I recommend you to start with the <a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">OWASP Top Ten Project</a> where you can read about the top ten security risks in web apps, and how you can prevent them.</p>

<p>Does all of this mean that you should avoid cookies altogether? Of course not. Let&#8217;s take a look at two ways to encrypt your cookies and detect possible changes made to them. Note that the following code snippets are taken from the <a href="http://lithify.me/">Lithium</a> core. (Make sure to check it out if you haven&#8217;t already!) Additionally, I&#8217;ve modified the code snippets a bit to make them easier to understand. Lithium handles the following techniques transparently, so in practice, you only add and read data and don&#8217;t need to care about the implementation details.</p>

<h2>Directions</h2>

<p>A secure way to ensure that no one has tampered with your cookies is called <a href="http://en.wikipedia.org/wiki/HMAC">HMAC</a> (Hash-based Message Authentication Code). In a nutshell, your cookie gets signed with a hash that is generated from your data and a secret password. As a result, if the data changes, the hash will change, too.</p>

<p>PHP provides a handy <a href="http://php.net/hash-hmac"><code>hash_hmac()</code></a> function that does the actual work for you. Here&#8217;s the code snippet from Lithium:</p>

<pre><code>public static function signature($data, $secret = null) {
	unset($data['__signature']);
	$secret = ($secret) ?: static::$_secret;
	return hash_hmac('sha1', serialize($data), $secret);
}</code></pre>

<p>It all boils down to calling <code>hash_hmac()</code> with an algorithm (in this case <code>sha1</code>), the actual data, and a secret password. Because you can only hash a string, you may need to serialize a non-scalar payload first. The signature will be appended to the payload, so you need to unset it first, so that the hash actually represents just the payload. It looks similar to this (let&#8217;s pretend that the static <code>signature</code> method is wrapped in a <code>Cookie</code> class and is public):</p>

<pre><code>// password and payload
$secret = 'phpadvent';
$data = array('christmas' => 'fun');

// create the signature
$signature = Cookie::signature($data, $secret);

// store the cookie
$data += array('__signature' => $signature);
setcookie('mycookie', serialize($data));</code></pre>

<p>To verify the cookie, remove the payload and generate the hash again. If the two hashes don&#8217;t match, Lithium raises a <code>RuntimeException</code>. This isn&#8217;t strictly necessary, but it makes sense in certain environments (you can then write exception handlers that log attack events, send emails, or block further requests).</p>

<pre><code>public function read($currentData, array $options = array()) {
// ....

$currentSignature = $currentData['__signature'];
$signature = static::signature($currentData);

if ($signature !== $currentSignature) {
	$message = "Possible data tampering: HMAC signature does not match
data.";
	throw new RuntimeException($message);
}
return $data;
}</code></pre>

<p>I recommend you read both the <a href="http://php.net/hash-hmac"><code>hash_hmac()</code> documentation</a> and the actual <a href="https://github.com/UnionOfRAD/lithium/blob/master/storage/session/strategy/Hmac.php">implementation</a> in Lithium.</p>

<p>Message digests are a good way to detect data tampering, but in a lot of cases, it is an even better idea to encrypt all of your data. In order to do this, make sure to have the <code>mcrypt</code> extension installed. I recommend you use the <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a> algorithm in <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29">CBC</a> mode (don&#8217;t use ECB, as it is considered <a href="http://www.adayinthelifeof.nl/2010/12/08/encryption-operating-modes-ecb-vs-cbc/">far less secure</a>).</p>

<p>The code for encryption is a bit more complicated, but it&#8217;s definitely worth the trouble.</p>

<pre><code>protected static $_vector = null;

public function __construct($secret) {
	$this->_config = array(
		'secret' => $secret,
		'cipher' => MCRYPT_RIJNDAEL_256,
		'mode' => MCRYPT_MODE_CBC,
		'vector' => static::_vector(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)
	);
}

protected static function _vector($cipher, $mode) {
	if (static::$_vector) {
		return static::$_vector;
	}

	$size = static::_vectorSize($cipher, $mode);
	return static::$_vector = mcrypt_create_iv($size, MCRYPT_DEV_URANDOM);
}

protected static function _vectorSize($cipher, $mode) {
	return mcrypt_get_iv_size($cipher, $mode);
}

public function encrypt($decrypted = array()) {
	$cipher = $this->_config['cipher'];
	$secret = $this->_config['secret'];
	$mode   = $this->_config['mode'];
	$vector = $this->_config['vector'];

	$encrypted = mcrypt_encrypt($cipher, $secret, serialize($decrypted),
$mode, $vector);
	$data = base64_encode($encrypted) . base64_encode($vector);

	return $data;
}

public function decrypt($encrypted) {
	$cipher = $this->_config['cipher'];
	$secret = $this->_config['secret'];
	$mode   = $this->_config['mode'];
	$vector = $this->_config['vector'];

	$vectorSize = strlen(base64_encode(str_repeat(" ",
static::_vectorSize($cipher, $mode))));
	$vector = base64_decode(substr($encrypted, -$vectorSize));
	$data = base64_decode(substr($encrypted, 0, -$vectorSize));

	$decrypted = mcrypt_decrypt($cipher, $secret, $data, $mode, $vector);
	$data = unserialize(trim($decrypted));

	return $data;
}</code></pre>

<p>The actual work is done by the <code>mcrypt_*</code> methods. (Lithium provides internal wrappers.) The constructor (not shown here) creates a vector (by calling <code>_vector()</code>) and sets the cipher (<code>MCRYPT_RIJNDAEL_256</code>), the mode (<code>MCRYPT_MODE_CBC</code>), and a custom secret. When <code>encrypt()</code> is called, the unencrypted payload is serialized and encrypted with <a href="http://php.net/mcrypt-encrypt"><code>mcrypt_encrypt()</code></a>. Because the encrypted data may contain incompatible characters for cookies, we need to <a href="http://php.net/base64-encode"><code>base64_encode()</code></a> it. Decrypting works in exactly the opposite way (decoding, decrypting, and unserializing). Here&#8217;s an example:</p>

<pre><code>// password and payload
$secret = 'phpadvent';
$data = array('christmas' => 'fun');

// encrypting
$cookie = new Cookie($secret);
$encrypted = $cookie->encrypt($data);

/* Possible output:
* string(88)
"aAH84W30XJTRC1aFdvleJdv3H0Dzj/TPLVSYKyWe2yo=LtoWXG8ewGK6btLnO2OLGsOfTc6T97TLwwogmMXORHI="
*/
var_dump($encrypted);

// of course, we can decrypt it again
$decrypted = $cookie->decrypt($encrypted);

/* Output:
* array(1) { ["christmas"]=> string(3) "fun" }
*/
var_dump($decrypted);</code></pre>

<p>If you are very careful, you can first add an HMAC signature to your payload and then encrypt it all.</p>

<h2>Tasting</h2>

<p>Now that we know the ingredients, lets bake secure cookies with Lithium:</p>

<pre><code>use lithium\storage\Session;

Session::config(array('default' => array(
	'adapter' => 'Cookie',
	'strategies' => array('Encrypt' => array('secret' => 'p$hp#4dv3nTT'))
)));

Session::write('mykey', 'myvalue');</code></pre>
	
<p>That was easy, right? Lithium provides you with a transparent abstraction to both session adapters (cookies and native PHP), and security strategies (HMAC and encryption), so you can mix them as you like. You can even write your own adapters (like a custom database adapter) and still profit from encryption strategies out of the box.</p>

<p>The key message I want you to take away is to take care of your cookies!  Don&#8217;t store a single bit more than necessary on the client side, encrypt it, and make sure it was not modified outside of your control.  PHP and the <code>mcrypt</code> extension provide you with everything you need, and good frameworks provide you with handy abstractions, so use them!</p>

<h2>Developer Gift</h2>

<p>Here&#8217;s a recipe for original viennese <a href="http://en.wikipedia.org/wiki/Vanillekipferl">Vanillekipferl</a>. You may need to convert the measurements into your own.

<ul>
 <li>300 grams of flour</li>
 <li>250 grams of butter (at room temperature)</li>
 <li>150 grams of ground hazelnuts</li>
 <li>100 grams of icing sugar</li>
 <li>1 teaspoon of vanilla sugar</li>
</ul>

<p>Roast the hazelnuts in a pan without fat, and then let them cool. Mix all ingredients together in a bowl until they contain no chunks of flour and the dough is smooth. Afterwards, wrap the dough into wrapping film, and put it into the refrigerator for one hour.</p>

<p>Preheat the oven to 160&#176;C. Chop the dough into small parts and form small Kipferl (U-Form, like seen in the <a href="http://en.wikipedia.org/wiki/Vanillekipferl">Wikipedia article</a>). Put them into the oven for about 15 minutes&#8201;&#8212;&#8201;they should only be slightly brown (not too dark!). While they are hot, turn them over into a mix of icing sugar and vanilla sugar so they are fully covered (like in the <a href="http://en.wikipedia.org/wiki/File:Vanillekipferl_Weihnachtsgebaeck.JPG">Wikipedia picture</a>).</p>

<p>Let them rest for a few days in a box before serving!</p>]]></description>
              <link>http://phpadvent.org/2011/bake-cookies-like-a-chef-by-michael-nitschinger</link>
              <guid>http://phpadvent.org/2011/bake-cookies-like-a-chef-by-michael-nitschinger</guid>
              <pubDate>Mon, 12 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Out with the Old</title>
              <dc:creator>Maggie Nelson</dc:creator>
              <description><![CDATA[<p>Jetpacks. Flying cars. Databases able to handle infinite amounts of data. Breakthrough after breakthrough, computer engineering forges a shiny future, and yet&#8230;</p>

<p>One of the first interview questions I was asked was to describe, in my own words, the difference between an inner join and an outer join. It is a question I have adopted, and I now ask it to every candidate. Over time, I&#8217;ve been interviewing more and more senior developers, most of whom know the correct answer, so this question has become a way to gaze into the developer soul instead, providing a brief glimpse of the developer&#8217;s professional experience. Typically, answers take one of the following paths:</p>

<ul>
    <li>A dry, textbook answer. Bonus points for using <code>table EMPLOYEES</code> in the example.</li>
    <li>A MySQL-specific answer, illustrated with a set of tables to support a blogging app.</li>
    <li>Data relationships (and therefore joins) explained as a set of properties of objects. Most answers here include <code>User</code> objects and <code>Friend</code> relationships.</li>
</ul>

<p>I see the last answer more frequently these days, which makes sense. NoSQL is making huge inroads in the world of software engineering, and frameworks are popping up left and right divorcing developers from the need to interact with databases (sorry, &#8220;data stores&#8221;) directly. The combination of Moore&#8217;s Law and developers&#8217; access to as much computing power as they need&#8201;&#8212;&#8201;or want&#8201;&#8212;&#8201;creates a situation where developers can get away with abandoning a schema-first approach to app design. This is great for those who have never learned SQL properly, or those who don&#8217;t want to feel shackled by a relatively inflexible schema and prefer to focus on business priorities instead.</p>

<p>Not designing the schema first is cool, but data still has to live somewhere and continue to be managed and monitored. We have not skipped over databases; we&#8217;ve just changed, quite drastically, how we think about them. Over time, relational databases battled each other, pushing features and vertical designs (I&#8217;m looking at you here, Oracle) that promised end-to-end data management. In the meantime, NoSQL data stores thought about separation of function and specialization. Instead of trusting relational databases to solve the problems behind the <a href="http://en.wikipedia.org/wiki/CAP_theorem">CAP theorem</a>, they went all postmodern on data-driven software and deconstructed how data is stored, retrieved, synchronized, and persisted within an app.</p>

<p>Gone are the days where a web app was a database with some PHP in front of it. Web apps are now layers and layers&#8201;&#8212;&#8201;a lot of them independent, many of them using completely different technologies, and some interacting with each other via HTTP-based APIs. The art of scaling web apps is the art of shifting bottlenecks around, and in data-first design, the bottleneck was frequently the monolith database. These days, you might encounter some of the following within your app:</p>

<ul>
    <li>A caching layer from which most stored data is retrieved, usually implemented using <a href="http://memcached.org/">Memcached</a> or <a href="http://redis.io/">Redis</a>.</li>
    <li>Decoupling the volume of user activity from the expectations of app responsiveness by delaying the computation of some tasks. This is sometimes implemented by using a queue-specialized data store&#8201;&#8212;&#8201;either by using a great key/value store like Redis or an off-the-shelf product like <a href="http://gearman.org/">Gearman</a>.</li>
    <li>Data that is separated horizontally across many databases&#8201;&#8212;&#8201;perhaps a few MySQL instances with sharded/replicated data.</li>
    <li>Data that is separated based on natural parameters, such as user data in a graph database like <a href="http://neo4j.org/">Neo4j</a> for easy relationship digging, and articles the users write in a MongoDB instance for quick reads and writes.</li>
    <li>A standalone search index of the content of your app in a search-specialized data store, such as <a href="http://lucene.apache.org/solr/">Solr</a>.</li>
    <li>A layer&#8201;&#8212;&#8201;invisible to the end use&#8201;&#8212;&#8201;that siphons samples data from designated data store locations, then crunches it until it&#8217;s transformed into information and, later on, knowledge.</li>
</ul>

<p>The bottlenecks still exist, but they are isolated explicitly in a way that can be either easily refactored or replaced with a new technology when it is invented. Your search might be slow, but in a few months, Solr might get replaced with X. Your articles might require more error-tolerant write mechanism, but in a few weeks, your MongoDB instances might get replaced with Y.</p>

<p>From the standpoint of an SQL aficionado, I enjoy seeing how relational databases continue to be used but are forced to evolve to fit the needs of the new world. Your MySQL is no longer responsible for searching or managing user relationships, but it may be used as a queueing mechanism, or perhaps an interim caching layer. Relational databases are no longer used as the end-all solution for data management, but they are not discarded and can still be used in a lot of the new ways developers build web apps. Perhaps, in a way, the slight distrust developers still have of NoSQL (e.g., how certain products are still &#8220;immature&#8221;) means that relational databases are here to stay purely out of inertia, but this also gives developers a chance to be creative with the existing technology.</p>

<p>Here are a couple of examples of using MySQL in interesting (and it&#8217;s up to you whether unwise) ways:</p>

<ul>
    <li>MySQL as a graph database, like Twitter&#8217;s <a href="http://engineering.twitter.com/2010/05/introducing-flockdb.html">FlockDB</a>.</li>
    <li>MySQL as document store, like FriendFeed&#8217;s extremely custom <a href="http://bret.appspot.com/entry/how-friendfeed-uses-mysql">schema design</a>.</li>
    <li><a href="https://github.com/ntemple/mysql-keyvalue">MySQL as a key/value store</a>. This lets you play with NoSQL concepts using MySQL.</li>
</ul>

<p>In the last decade, we have changed how we interact with relational databases and what we expect from them. NoSQL has not (yet) offered us a flying car in the form of a be-all and end-all data store. In the meantime, we must make do we the tools that we already have, while hoping for and working on new inventions!</p>

<p>Until next time! (Starts her jetpack and flies away.)</p>

<h2>Developer Gift</h2>

<p>Gadgets and software are always nice, but think about making your developer gal or guy&#8217;s workspace a bit nicer. Nothing makes your desk feels cozier, saner, and healthier than an awesome plant. My favorite is the easy-to-grow <a href="http://en.wikipedia.org/wiki/Monstera_deliciosa">monstera deliciosa</a>, also known as the Swiss cheese plant. If you suspect your gal or guy to be terrible at plant management, I suggest a set of nicely potted succulent plants. They&#8217;re easy to grow and nigh impossible to kill. Perhaps a terrarium of succulent plants from <a href="http://etsy.com/shop/SucculentDESIGNS">this Etsy shop</a>?</p>]]></description>
              <link>http://phpadvent.org/2011/out-with-the-old-by-maggie-nelson</link>
              <guid>http://phpadvent.org/2011/out-with-the-old-by-maggie-nelson</guid>
              <pubDate>Sun, 11 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Better Object-Oriented Arrays</title>
              <dc:creator>Ryan Parman</dc:creator>
              <description><![CDATA[<p>I&#8217;ve been working on developer-facing software and SDKs in PHP for nearly a decade, and through the experience of supporting these developers, I&#8217;ve learned something interesting about the PHP community at-large. The majority of PHP developers have a very good understanding of native types (e.g., strings, arrays, integers, booleans). Since they&#8217;re the lowest common denominators of the PHP language, it&#8217;s generally pretty easy for developers to understand these types.</p>

<p>But the moment you introduce concepts like <em>objects</em> as return types, people suddenly can&#8217;t figure out how the darn thing works. It&#8217;s remarkably similar to when people forget how to drive the instant it starts raining. Most PHP software has trained us to expect native types as responses, but if you return something like a `SimpleXMLElement` object or some other sort of custom object, confusion erupts!</p>

<h2>Stopping the Insanity with Collections</h2>

<p>In an effort to find a better solution to the array versus object debacle, I started investigating the possibility of object-oriented arrays in PHP. This way, you can return an array-like object which behaves just like you&#8217;d expect an array to, but has all of the power of an object.</p>

<p>PHP has two classes called <code>ArrayObject</code> and <code>ArrayIterator</code> that are more like stubs than anything useful. What they provide, however, is a reasonably solid foundation for building a useful object-oriented array class on top of. These classes also implement a set of interfaces that give us a significant amount of functionality relatively for free.</p>

<p>Since the word <em>array</em> already has a specific meaning in PHP, I&#8217;ll call our new object-oriented array class the <code>Collection</code> class. The goal of this class is to behave identically to an array, but support a variety of methods like the kind you&#8217;d find in everything-is-an-object languages like Ruby and JavaScript.</p>

<h2>Constructor</h2>

<p>Let&#8217;s begin with our class definition and constructor:</p>

<pre><code>class Collection implements IteratorAggregate, ArrayAccess, Countable, Serializable
{
	private $collection;
	private $iterator;

	public function __construct($value = array())
	{
		$this-&gt;collection = new ArrayObject($value, ArrayObject::ARRAY_AS_PROPS);
		$this-&gt;iterator = $this-&gt;collection-&gt;getIterator();
	}
}</code></pre>

<p>Note: The <code>IteratorAggregate</code> interface extends the <code>Traversable</code> interface, which enables <code>foreach</code>ing through the collection.</p>

<h2>Interface Methods</h2>

<p>Next, we need to implement all of the methods that are defined by the interfaces. These include:</p>

<ul>
    <li><code>current</code>, <code>key</code>, <code>next</code>, <code>rewind</code>, <code>seek</code>, and <code>valid</code> from the <code>Traversable</code> interface.</li>
    <li><code>getIterator</code> from the <code>IteratorAggregate</code> interface.</li>
    <li><code>offsetExists</code>, <code>offsetGet</code>, <code>offsetSet</code>, and <code>offsetUnset</code> from the <code>ArrayAccess</code> interface.</li>
    <li><code>count</code> from the <code>Countable</code> interface.</li>
    <li><code>serialize</code> and <code>unserialize</code> from the <code>Serializable</code> interface.</li>
</ul>

<p>For the most part, these can be implemented by simply calling out to the already-existing methods on the <code>$this->collection</code> and <code>$this->iterator</code> properties.</p>

<p>If you want your collections to be able to be serialized and unserialized, you&#8217;ll need to custom implement these methods. The trickiest thing to watch out for is handling cases where your collection contains a <code>SimpleXMLElement</code> element. Since <code>SimpleXMLElement</code> can&#8217;t be serialized, you&#8217;ll need to manually convert the object to an XML string on serialization, and re-parse it on unserialization.</p>

<h2>Converting Types</h2>

<p>So far, you&#8217;ll already be able to do things like this:</p>

<pre><code>$data = new Collection(array(1, 2, 3, 4, 5, 'a', 'b', 'c'));
$numbers = new Collection();
$letters = new Collection();

foreach ($data as $entry)
{
	if (is_int($entry))
	{
		$numbers[] = $entry;
	}
	elseif (is_string($entry))
	{
		$letters[] = $entry;
	}
}</code></pre>

<p>However, since array functions in PHP require the inputs to be <em>real</em> arrays, we&#8217;ll need to be able to easily export the collection to an old-school array.</p>

<pre><code>public function to_array()
{
	return $this-&gt;collection-&gt;getArrayCopy();
}</code></pre>

<p>Maybe you even want to add functionality to implement things like <code>to_json()</code>, <code>to_yaml()</code>, or <code>to_object()</code>. This is really easy to do with off-the-shelf tools found in PHP itself and popular third-party packages (such as <a href="http://components.symfony-project.org/yaml/">Symfony YAML</a>).</p>

<h2>Magic Methods</h2>

<p>What would an awesome collection class be without some magic?</p>

<pre><code>// Support looking up nodes using $obj-&gt;key
// Also, call methods without parenthesis: $obj-&gt;method
public function __get($name)
{
	if (method_exists($this, $name))
	{
		return $this-&gt;$name();
	}
	elseif ($this-&gt;exists($name))
	{
		return $this[$name];
	}

	return null;
}

// Support setting values with $obj-&gt;key = $value
public function __set($name, $value)
{
	if (method_exists($this, $name))
	{
		return $this-&gt;$name($value);
	}

	$this[$name] = $value;
	return $this;
}

// Support cloning this object
public function __clone()
{
	$this-&gt;collection = clone $this-&gt;collection;
	$this-&gt;iterator = clone $this-&gt;iterator;
}

// Support echo $obj
public function __toString()
{
	print_r($this-&gt;collection-&gt;getArrayCopy());
}</code></pre>

<h2>Now What?</h2>

<p>So, you&#8217;ve put together this class. Now what? Well, now you have an object that behaves like an array, can do all of the things that an array is designed to do, and has all of the advantages of being an object. Let&#8217;s look at what works and what doesn&#8217;t. (Pretend we&#8217;ve also taken the time to implement methods like <code>first</code> and <code>last</code>.)</p>

<pre><code>$array = array(
	'key1' =&gt; 'value1',
	'key2' =&gt; 'value2',
	'key3' =&gt; 'value3',
	'key4' =&gt; 'value4',
	'key5' =&gt; 'value5'
);

$array[0]       // Error!
$array['key1']  // &quot;value1&quot;
$array-&gt;key1    // Error!
rewind($array)  // &quot;value1&quot;
end($array)     // &quot;value5&quot;
$array-&gt;first() // Error!
$array-&gt;first   // Error!
$array-&gt;last()  // Error!
$array-&gt;last    // Error!

array_values($array); // [&quot;value1&quot;, &quot;value2&quot;, &quot;value3&quot;, &quot;value4&quot;, &quot;value5&quot;]</code></pre>

<p>Versus&#8230;</p>

<pre><code>$collection = new Collection(array(
	'key1' =&gt; 'value1',
	'key2' =&gt; 'value2',
	'key3' =&gt; 'value3',
	'key4' =&gt; 'value4',
	'key5' =&gt; 'value5'
));

$collection[0]       // Error
$collection['key1']  // &quot;value1&quot;
$collection-&gt;key1    // &quot;value1&quot;
rewind($collection)  // &quot;value1&quot;
end($collection)     // &quot;value5&quot;
$collection-&gt;first() // &quot;value1&quot;
$collection-&gt;first   // &quot;value1&quot;
$collection-&gt;last()  //&quot; value5&quot;
$collection-&gt;last    // &quot;value5&quot;

array_values($collection-&gt;to_array); // [&quot;value1&quot;, &quot;value2&quot;, &quot;value3&quot;, &quot;value4&quot;, &quot;value5&quot;]</code></pre>

<p>You can now access collection keys as indexes (like arrays) or properties (like objects). The advantage here is that you can extend your class even further by implementing methods such as <code>push</code>, <code>pop</code>, <code>first</code>, <code>last</code>, <code>flatten</code>, <code>slice</code>, <code>sort_by</code>, <code>reduce</code>, <code>each</code>, <code>map</code>, <code>min</code>, <code>max</code>, <code>every</code>, <code>any</code>, <code>grep</code>, <code>ungrep</code>, and more, all by manipulating the value of <code>$this->collection</code>. You can&#8217;t do that with an old-school array!</p>

<h2>Homework</h2>

<p>To make a really robust collection class, I would recommend borrowing as many ideas as possible from everything-is-an-object languages like <a href="http://ruby-doc.org/core-1.9.3/Array.html">Ruby</a> and <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array">JavaScript</a>. Once you have your powerful collection class fully implemented, you&#8217;ll never have to worry about needle-haystack issues ever again, and your developer-customers will have far less confusion functionality when using your code.</p>

<p>At some point, maybe we can do the same thing with object-oriented strings. :-)</p>

<h2>Developer Gift</h2>

<p>I have two ideas.</p>

<p>When I was working on <a href="http://simplepie.org/">SimplePie</a>, the developers would post our Amazon wishlists online in case anybody wanted to get us something in appreciation for the software. I would randomly get cool presents left on my doorstep throughout the course of the year. It was kind of like a Christmas present that would sneak up and pounce when I wasn&#8217;t looking. Much like Hobbes the tiger. It was awesome.</p>

<p>If the developer in your life doesn&#8217;t have any kind of wishlist, I would say the single greatest tool I use in a normal programming-intensive workday is a really good set of noise-canceling headphones. There are few things better than being able to fall into the coding zone with great tunes, and very legitimately not be disturbed by someone walking over to your desk and interrupting you. You won&#8217;t be able to hear them! :-)</p>]]></description>
              <link>http://phpadvent.org/2011/better-object-oriented-arrays-by-ryan-parman</link>
              <guid>http://phpadvent.org/2011/better-object-oriented-arrays-by-ryan-parman</guid>
              <pubDate>Sat, 10 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Merry Error Handling</title>
              <dc:creator>Samer Atiani</dc:creator>
              <description><![CDATA[<p>PHP does not enjoy the same consistency in error (and exception) handling as other languages,
mostly due to historical reasons and the lack of a formal
specification. But, there are things that you can do to make error handling
saner and easier to maintain.</p>

<p>PHP has multiple categories of errors and exceptions, each with its own handling
semantics within the PHP interpreter. For our purposes, we can classify these
into the following categories:</p>

<ul>
    <li>Fatal errors, like out-of-memory and syntax errors, <code>E_ERROR</code>, <code>E_CORE_ERROR</code>, and
  <code>E_PARSE</code>.</li>
    <li>User errors, including <code>E_USER_ERROR</code>, <code>E_WARNING</code>, <code>E_PARSE</code>, and all other
  non-fatal errors.</li>
    <li>Exceptions (all subclasses of the <code>Exception</code> class).</li>
</ul>

<p>Fatal errors are triggered from within the PHP
interpreter and cannot be triggered by app code written in PHP. (It
is possible, however, that some PHP extensions written in C may trigger fatal errors.)</p>

<p>User errors are largely deprecated in favor of exceptions,
although they still get triggered by the PHP interpreter and some third-party
libraries.</p>

<p>Exceptions behave the same way exceptions do in many
other languages like Java, Python, and Ruby.</p>

<p>In an ideal world, all these categories
would be condensed into one category, so you could apply the same rules and
syntax to all of them. However, as you might have guessed, we do not live in an
ideal world. Nonetheless, we will try to approximate it.</p>

<h2>Fatal errors</h2>

<p>There is <a href="http://www.phpcodebase.com/catch-fatal-errors-in-php/">a lot of literature out there</a> about how to handle fatal errors using
shutdown functions. Basically, <code>set_error_handler()</code> will
not work for fatal errors. Instead, you can use <code>register_shutdown_function()</code> and
pass it a function that performs some custom actions when fatal errors occur.</p>

<p>The problem is that, by the time the shutdown function is called, the call stack
is emptied, and you have no useful backtrace to work with, except for where  in the file
the error has occurred. If you try to call <code>debug_backtrace()</code> in
your shutdown function, it will return an empty array.</p>

<p>One way to work around this is to log a global variable in the shutdown function
that can help debug the problem. This global variable could be the
session identifier, user identifier, or anything that can help correlate log lines produced
by the shutdown function with other log lines produced within the normal run of
the app.</p>

<p>Furthermore, following <a href="http://stackoverflow.com/questions/277224/how-do-i-catch-a-php-fatal-error">some examples</a>, calling <code>error_get_last()</code>
means if any additional errors or warnings occur before the shutdown
function is called, these will overwrite the error that actually caused the
code to halt. Sadly, there is no way to avoid this, except to make sure
these errors do not happen in the first place. These usually happen if PHP is
incorrectly configured, or if you use poorly implemented third-party modules or C extensions
that throw errors on shutdown.</p>

<h2>Unifying user errors and exceptions</h2>

<p>Much literature also exists about handling user errors, including in the PHP
manual. However, most of the error handling solutions around suffer from two
drawbacks:</p>

<ul>
    <li>You have to maintain two separate handlers for errors and exceptions.</li>
    <li>You still cannot handle PHP errors like exceptions locally in the code. Instead, you have to rely on a global error handler.</li>
</ul>

<p>The first drawback can be worked around by having both handlers simply call a
central error handling facility instead of duplicating code. The following trick
to wrap PHP errors as exceptions can be used to ameliorate the second drawback:</p>

<pre><code>&lt;?php

// These should usually be in your php.ini, but I'm putting it here to
// make sure this demonstration is portable across different configurations
ini_set('display_errors', 'stdout');
error_reporting(E_ALL);

function handle_error($errno, $errstr, $errfile, $errline) {
    // Note that you could also check for a larger set of PHP errors like:
    // $is_halting_error = $errno & (E_USER_ERROR | E_WARNING | E_USER_WARNING);
    $is_user_error = $errno & E_USER_ERROR;
    if ($is_user_error) { 
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    } else {
        // do some logging, custom actions, or even ignore the error
    }
}

set_error_handler('handle_error');

function test_fake_error() {
    trigger_error('Test error', E_USER_ERROR);
}

function test_caught_error() {
    try {
        test_fake_error();
    } catch (Exception $e) {
        print &quot;I caught the exception with message: &quot; . $e-&gt;getMessage() . &quot;\n&quot;;
    }
}

function test_uncaught_error() {
    test_fake_error();
}

test_caught_error();
test_uncaught_error();
</code></pre>

<p>If you run the program above with a PHP 5.3 interpreter, then something like
this should be on the standard output:</p>

<pre><code>I caught the exception with message: Test error

Fatal error: Uncaught exception 'ErrorException' with message 'Test error' in test.php:22
Stack trace:
#0 [internal function]: handle_error(256, 'Test error', 'test.php', 22, Array)
#1 test.php(22): trigger_error('Test error', 256)
#2 test.php(34): test_fake_error()
#3 test.php(38): test_uncaught_error()
#4 {main}
  thrown in test.php on line 22</code></pre>

<p>As you can see from this example, you can take advantage of both localized
try/catch facilities as well as a full stack trace that comes for free from
wrapping the error as an exception!</p>

<p>As an aside, you may notice something strange in the stack trace above; it looks
as if the error handling function was called from inside the function that
triggered the error. This is because, behind the scenes, what <code>trigger_error()</code>
is really doing is simply calling error handlers with information about the
user-defined error. If there is a user-defined error handler, then that is called
first before calling the default error handler. (For details, see
<a href="http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_builtin_functions.c?view=markup#l1383"><code>trigger_error()</code></a> and
<a href="http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend.c?view=markup#l978"><code>zend_error()</code></a>.)
The call from
<code>trigger_error()</code> to the user-defined error handler is done using the
<code>call_user_function_ex()</code> C function (which happens to be the same C function used
in PHP&#8217;s <code>call_user_func()</code>), which records the call in the stack trace and leads
to the backtrace seen above.</p>

<h2>Developer Gift</h2>

<p>Look for those unsung heroes in your workplace, the ones who keep things humming along without anyone ever noticing, simply because they are so good at what they do. Send them an email, ask to accompany them for a day or two, and put yourself in their shoes. It will most likely be an enlightening experience for you&#8201;&#8212;&#8201;a chance for you to explore what you have come to take for granted. Your interest in what they do will be a rare acknowledgement&#8201;&#8212;&#8201;a gift!&#8201;&#8212;&#8201;of how critical they are.</p>]]></description>
              <link>http://phpadvent.org/2011/merry-error-handling-by-samer-atiani</link>
              <guid>http://phpadvent.org/2011/merry-error-handling-by-samer-atiani</guid>
              <pubDate>Fri, 09 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Integration Testing</title>
              <dc:creator>Wez Furlong</dc:creator>
              <description><![CDATA[<p>At some point in our respective programming careers, most of us have
heard that Test-Driven Development (TDD) is what we should be doing.</p>

<p>The TDD thesis is that we write tests (known as <em>unit tests</em>)
that consume the functions, classes, and interfaces of the code that we
intend to write <em>before</em> we write it, and that doing this
improves the quality of our code due to increased foresight and
better ability to catch a specific type of bug known as a
<em>regression</em>, which is the technical term your boss uses for
something that worked fine before you added that last bit of code.</p>

<p>The gist of TDD is:</p>

<ul>
   <li>Each test should test one unit of code.</li>
   <li>Tests should not cross process boundaries in a program.</li>
   <li>Tests should not establish network connections.</li>
</ul>

<p>If you&#8217;re writing tests that don&#8217;t follow these rules, tsk tsk, you&#8217;re
doing unit testing wrong! The mantra is that instead of doing this, you
need to tease apart the code so that you can introduce <em>mocks</em> and
fake access to those other components.</p>

<p>While I&#8217;m on board with the idea that we should be writing code with
testing in mind, it is all too easy to get swept away with the purist
TDD approach, and&#8201;&#8212;&#8201;before you know it&#8201;&#8212;&#8201;you&#8217;re not actually writing code
anymore; you&#8217;re thinking about how to change your real code so that you
can write fake code to test your real code. (As a humorous
semi-diversion, getting lost in JUnit-derived test frameworks just makes
me think of <a href="http://discuss.joelonsoftware.com/default.asp?joel.3.219431">building a spice rack</a>.)</p>

<p>The problem I see with this approach, especially if you&#8217;re retrofitting
test facilities to a project, is that the cost of implementing all the
mocks and fakes can be prohibitive, and it may not even be an effective
use of time! Are your users going to run your fake code? What if
there&#8217;s a bug in your fake code that doesn&#8217;t match up to the real world?
Will your tests save you from that problem?</p>

<h2>Integration Testing</h2>

<p>There&#8217;s another type of test known as an integration test that describes
testing the ability of your program to talk to other modules, databases,
and services. The idea is that your test suite starts up instances of
its own services (web server, database, &#38;c.) for the test programs to
execute against.</p>

<p>Running its own services guarantees that everyone who runs the tests are
running with a consistent environment; this is how you eliminate the &#8220;works for me&#8221; class of problem.</p>

<p>I&#8217;ve recently started to build up a test suite for <a href="http://mtrack.wezfurlong.org">Mtrack</a> (yes, it
is <em>long</em> overdue) that uses this approach. Mtrack has a couple of key interfaces:</p>

<ul>
   <li>Web UI (PHP, with a bit of Backbone.js for the frontend)</li>
   <li>REST API</li>
   <li>SSH access to repositories</li>
</ul>

<p>It also relies on a couple of services, depending on how it has been
configured:</p>

<ul>
   <li>Zend Framework Lucene Full Text search index</li>
   <li>Solr Full Text search index</li>
   <li>PostgreSQL database</li>
   <li>SQLite database</li>
</ul>

<p>A driver script called <code>runtests</code> sets up an Apache web server,
initializes a SQLite database, starts Solr, starts an SSH server, and
launches the Selenium server. It then runs the Perl <code>prove</code> tool to
execute the test programs.</p>

<p>I tend to use a <a href="http://shiflett.org/blog/2006/jan/test-simple-for-php">Test::More</a>-derived test framework in my integration
tests (because we work with Perl and other systems a lot); you can
certainly use PHPUnit if you&#8217;re more comfortable with that. I like the
Test::More style, because it feels very lightweight.</p>

<p>With the services up, we can then write tests that exercise
our code via the REST API; these tests can use PHP&#8217;s streams or
cURL functions to talk to the web server. The test driver for Mtrack
exports the web server port number to an environment variable, so
the test program knows which server it should talk to.</p>

<p>The Mtrack REST API tests look something like this (simplified for the
sake of this article):</p>

<pre><code>&lt;?php
require 'Test/init.php' // Include test functions.
plan(10);               // Plan to run 10 tests.

// This makes a POST to the /ticket API, returning the
// HTTP status code, the headers, and the content. It
// automatically converts to/from JSON and gets the
// host and port from the environment variables set by
// the runtests script.
list($st, $h, $body) = rest_api_func('POST', '/ticket',
    null, null, array(
      'summary' =&gt; 'my test ticket',
      'description' =&gt; 'the body of the ticket'
    ));
if (!is($st, 200, 'created ticket')) {
  // Failed; this is not something we expect, so dump
  // out the body.
  diag($body);
}</code></pre>

<p>If the script doesn&#8217;t run 10 tests, the prove utility will fail the test
run, because something unexpected happened. If the <code>is()</code> function
returns false (indicating that something didn&#8217;t work), then that will
cause the test to fail and indicate where and why. We augment that by
outputting some diagnostics via the <code>diag()</code> function.</p>

<p>We use Selenium (albeit very lightly right now) to drive through some
workflows like creating a new ticket via the web UI (and this has
already caught a couple of corner cases for fresh installs).</p>

<p>The SSH server isn&#8217;t currently used by tests, but it is there to validate
that the repository creation and permissions work correctly when folks
use their SCM tools (<code>hg</code>, <code>git</code>, <code>svn</code>) over SSH.</p>

<p>I use a couple of command line options to toggle Selenium on and off (it
takes more than a few seconds to launch, making the tests take longer to
run), and another to switch between using the ZF Lucene code and the Solr
search server.</p>

<p>Each time the <code>runtests</code> script is run, it wipes out the Solr, SQLite, and
other state that was initialized from the last run so that we have a
consistent environment on each run.</p>

<h2>Summing Up</h2>

<p>Automated testing is definitely something that I would advocate to
anyone writing any kind of serious code. Designing your code for
testing from the outset is also strongly desirable. Unit testing is
important, but don&#8217;t get swept up in the purist approach; mocks and
fakes have their uses, but if you&#8217;re investing a significant amount of
time to build them up, you may want to consider spending that time on
automating your integration tests instead.</p>

<h2>Developer Gift</h2>

<p>It can be tricky to think of good gifts; so much of what software
developers do is intangible. I&#8217;ve come to appreciate things that help
me relax and unwind, and these days, this tends to be assisted by a nice
pour of a single malt whiskey. Depending on your budget and your
insight into the tastes of your prospective gift recipient you might
consider:</p>

<ul>
   <li><a href="http://thinkgeek.com/homeoffice/kitchen/ba37/">Whiskey stones</a>. &#8220;on the rocks&#8221; is not something you hear too often
   from a single malt drinker, because the ice melts and dilutes the complex
   flavors. Whiskey stones are a non-ice alternative.</li>
   <li><a href="http://www.masterofmalt.com/whiskies/glenmorangie/glenmorangie-10-year-old-original-glasses-whisky/">A nice set of tumblers</a>. (Here&#8217;s <a href="http://www.thewhiskyexchange.com/P-7235.aspx">another option</a>.) I have a couple of nice, weighty glasses that I
   particularly enjoy handling. If your giftee is really into tasting
   and nosing, there are special whiskey snifters to be had.</li>
   <li>A bottle of whiskey. There&#8217;s an element of taste to factor in here;
   some have very strong flavors that might be fine for an occasional
   glass, but otherwise unappreciated. If you have no idea, try to
   find out if there are favorites, and go for something similar.
   If you really have no idea, find someone else that does, and
   try to avoid the cheaper blends; it&#8217;s better to go for a smaller
   bottle of something nice than a larger bottle of something not.</li>
</ul>]]></description>
              <link>http://phpadvent.org/2011/integration-testing-by-wez-furlong</link>
              <guid>http://phpadvent.org/2011/integration-testing-by-wez-furlong</guid>
              <pubDate>Thu, 08 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Twilio in Two Minutes</title>
              <dc:creator>Elizabeth Naramore</dc:creator>
              <description><![CDATA[<p>I love <a href="http://twilio.com/">Twilio</a>. If you&#8217;re not familiar with Twilio and the amazing voice and text messaging stuff you can do with it, you&#8217;re in luck! I&#8217;m going to show you a few things you can try in a matter of minutes.</p>

<h2>An emergency line for the kids</h2>

<p>For $2 per month, I set up an emergency toll-free phone number for my kids. They can call this number from any phone, anywhere in the US, for free. The toll-free number will ring my phone, then their dad&#8217;s phone, then their grandparents&#8217; phone, and if all else fails, then a neighbor&#8217;s phone. It will try each phone number until it finds one that answers. Basically, the kids can call this one number when they urgently need to reach one of us, and they won&#8217;t have to remember a bunch of phone numbers. They also won&#8217;t need any money. $2 per month is not a lot to pay for my own peace of mind. Setting this up was easy; here&#8217;s how I did it.</p>

<p>First, make sure you have a <a href="http://twilio.com/">Twilio</a> account and somewhere to host your files. I use Engine Yard&#8217;s <a href="http://orchestra.io/">Orchestra PHP platform</a> and <a href="http://github.com/">GitHub</a>, but you can use whatever works for you.</p>

<p>To make the app, you&#8217;ll first need the <a href="https://github.com/twilio/twilio-php">Twilio PHP library</a>.</p>

<p>If you want to copy and paste some PHP, you can either use the <a href="http://labs.twilio.com/twimlets/source/findme">Find Me Twilio Twimlet</a> or the <a href="http://twilio.com/docs/howto/callscreening">Call Screening</a> guide in their list of <a href="http://twilio.com/docs/howto/">HowTos</a>, depending upon what you want to do. You can also avoid writing your own PHP entirely by using the <a href="http://labs.twilio.com/twimlets/findme">hosted Find Me Twimlet</a>, but you have a little less control.</p>

<p>If you want to make everything from scratch, feel free. There are numerous <a href="http://twilio.com/docs/quickstart/">Twilio Quickstart Guides</a>.</p>

<p>Make sure you modify the PHP to include your own phone numbers and Twilio account information (<code>$id</code> and <code>$token</code>), and upload it to where it&#8217;s being hosted.</p>

<p>Next, get a <a href="http://twilio.com/pricing">phone number from Twilio</a>, and <a href="https://www.twilio.com/user/account/phone-numbers/incoming">provide the URL of where to go when that phone number is called</a> (where you just put your code). The number is now ready to be used!</p>

<p>I think this idea is not only good for young kids, but also for teenagers and even college kids. And, what about aging parents or family and friends traveling around? Knowing they can always call a toll-free number and get help if they need it is something that should make everybody feel better.</p>

<h2>Personal messages from afar</h2>

<p>My Dad turns 70 this January. I thought it would be kind of awesome to get quotes from some family and friends that he hasn&#8217;t seen in a while. The only problem is that he has friends all over the world, and a lot of them aren&#8217;t too tech savvy. They can sometimes use email, but they don&#8217;t know about Facebook, Twitter, or even Microsoft Word.</p>

<p>I came up with the idea that I could get them to record a small message for him to wish him a happy birthday, burn all the messages onto a CD, and give it to him as a gift. Hearing someone&#8217;s voice is much more personal than an email or card, and this will be one gift that he will always remember. Because many of them don&#8217;t know how to record something, I needed to make it easy for them to record a message for him and send it to me.</p>

<p>Twilio makes this super easy!</p>

<ol>
    <li>Get a Twilio account. (You don&#8217;t need anything else, unless you want to make this more robust and do more things.)</li>
    <li>Check out the <a href="http://labs.twilio.com/twimlets/voicemail">Voicemail Twimlet</a>. Give it the parameters you want, then grab the URL that is generated.</li>
    <li>Get a phone number from Twilio and in hook it up to the URL the Twimlet just returned.</li>
    <li>Distribute the number with an explanation of what it&#8217;s for. When someone calls, they will be prompted to leave a message, and you will get an email with a link to an MP3 of that message.</li>
    <li>As emails come in, you can follow the link and grab a copy of the message they left, download it, and then burn them all to a CD.</li>
</ol>

<p>I think this also would be cool for &#8220;get well&#8221; messages for a hospital-bound friend, or a loved one that is stationed overseas. Responses could be sent to them individually, or to someone else who could compile them first.</p>

<p>Basically, there is no limit to what Twilio can do; the only limit is your own imagination. Go check out their <a href="http://twilio.com/docs/quickstart/">Quickstart Guides</a>, their <a href="http://twilio.com/docs/howto/">HowTos</a>, and their <a href="http://labs.twilio.com/twimlets/">Twimlets<a/>, and make your life or someone else&#8217;s better today!</p>

<h2>Developer Gift</h2>

<p>My first thought for a developer gift were <a href="http://unicahome.com/p65219/miscellaneous/pancake-floor-pillows-by-todd-von-bastiaans.html">these awesome pancake cushions</a>, but nobody is going to spend that much, even for something that cool. Instead, how about <a href="http://www.amazon.com/Twelve-South-BookBook-15-inch-Hardback/dp/B003CJYE6W/">these leather cases for iPods, iPads, and MacBooks that resemble old books</a>? They&#8217;re called BookBooks, and they are made by Twelve South. I think these are awesomely unique and help keep your devices separate from the sea of others.</p>

<p>Also, I have personally asked for some <a href="http://arduino.cc/">Arduino</a> goodies, so I hope Santa comes through!</p>]]></description>
              <link>http://phpadvent.org/2011/twilio-in-two-minutes-by-elizabeth-naramore</link>
              <guid>http://phpadvent.org/2011/twilio-in-two-minutes-by-elizabeth-naramore</guid>
              <pubDate>Wed, 07 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Dates and Times</title>
              <dc:creator>Evert Pot</dc:creator>
              <description><![CDATA[<p>Having dealt with a lot of dates and times&#8201;&#8212;&#8201;and the calculations between them&#8201;&#8212;&#8201;
recently, I thought it might be a good idea to write down some of the issues
I&#8217;ve encountered.</p>

<p>The truth is, dates and times are hard! There are many different rules 
that make dealing with dates and times non-trivial. Often, people 
make mistakes, causing loss of information and general confusion.</p>

<h2>Deciding on a format</h2>

<p>One of the observations I&#8217;ve made is that nearly every system out there
lacks a standard for passing around date and time values.</p>

<p>The most common formats are MySQL (YYYY-MM-DD HH:MM:SS),
timestamps (what <a href="http://php.net/time">time()</a> produces),
and <a href="http://php.net/manual/en/class.datetime.php">DateTime</a>.</p>

<p>There are benefits to all of these, but it&#8217;s important that you need to decide on one. 
Make sure any date/time that enters your
app through any means is converted immediately to this standard.
This includes, for example, the result of a MySQL query, data from <code>$_POST</code>,
or the response from a web service.</p>

<p>Make sure this enters your coding standards document.</p>

<h2>Using DateTime</h2>

<p>Deciding on a standard date format and following it religiously is much more
important than which standard you choose. If you have a choice, though, I recommend
the <a href="http://pt.php.net/datetime">DateTime</a> object.</p>

<p>The standard inclusion of the DateTime object in PHP is one of
the best things that has happened to PHP in recent times. It replaces all the 
functionality of the existing date functions, and there&#8217;s really no need
to use anything else.</p>

<p>One of the benefits you&#8217;ll get is that you can <a href="http://php.net/manual/en/language.oop5.typehinting.php">type hint</a>
it like every other class, which means it will be easier to spot bugs, and 
it&#8217;s self-documenting. Also, you can pretty much treat it like a timestamp:</p>

<pre><code>
$dt1 = new DateTime('yesterday');
$dt2 = new DateTime('next wednesday');

if ($dt1 &gt; $dt2) {
    echo "Hell froze over!\n"
};
</code></pre>

<p>As you can see, because DateTime is actually a PHP extension, it
gets the privilege of overloading operators such as &#60; and &#62;. Plus,
it handles timezones.</p>

<p>DateTime also makes it easy to do relative calculations. If you want to
increase a date by exactly one month, how many seconds you need to add the
start date depends on the month of the year, wether it&#8217;s a leap year or not,
which timezone you&#8217;re in, and whether a 
<a href="http://en.wikipedia.org/wiki/Leap_seconds">leap second</a> has been
scheduled that year. It&#8217;s easier let DateTime do it:</p>

<pre><code>
$dt = new DateTime('December 25th, 2011');
$dt-&gt;modify('+1 month');
</code></pre>

<h2>Using time zones</h2>

<p>I&#8217;ve noticed that a lot of people simply use their local 
timezone. This is a bad idea, because it&#8217;s not always 
immediately clear, it&#8217;s ambiguous, and it can cause 
obscure bugs. It will also not always be possible to convert to 
different timezones if your app ends up going international.</p>

<p>The reason it&#8217;s ambiguous is simple. Every year, in most European countries,
the end of <a href="http://en.wikipedia.org/wiki/Daylight_saving_time">Daylight savings time</a> is the last Sunday in 
October. On that day, every second between 02:00
 and 03:00 occurs twice. Thus, one ambiguity when using time zones is that
these seconds that occur twice are not unique, so you can no longer determine
if a time is referring to before the switchover or after. This can cause bugs when
doing date comparisons. Adding a second could mean the same thing
as subtracting 59 minutes and 59 seconds.</p>

<p>The start of DST is similar, which is why you might see gaps in log files and
whatnot.</p>

<p>So, make sure that when you deploy your app, the server as 
well as PHP are configured to use UTC or GMT. UTC time is time zone independent,
so every second of the year is, well, unique.</p>

<p>You&#8217;ll have to get into the habit of converting times
to your local time zone in your presentation layer. On the plus side,
it will be easy to support other time zones in the future.</p>

<p>You can always accurately convert from UTC to your local
time zone, but you cannot always accurately convert from your local time zone to 
UTC. (It is a lossy conversion.)</p>

<pre><code>
// Changing time zones
$dt = new DateTime('2011-10-07 12:00:00');
$dt-&gt;setTimeZone(new DateTimeZone('Europe/Lisbon'));

echo $dt-&gt;format(DateTime::RFC2822);
</code></pre>

<h2>Storing dates and times in MySQL</h2>

<p>There are three possible data types you can use to store dates and times in MySQL. You can
use DATETIME, TIMESTAMP, or INT (for storing a timestamp).</p>

<p>DATETIME is a popular choice, and in most cases, it&#8217;s fine.
Just remember that DATETIME is 8 bytes, whereas a TIMESTAMP
 or INT is just 4 bytes. The biggest benefit of  DATETIME is that it&#8217;s easy to do
calculations in queries, whereas this may is harder with a TIMESTAMP and INT.</p>

<p>I personally dislike TIMESTAMP, because it does 
automatic time zone conversion. This is fine if you keep 
everything set to UTC, but if this ever changes, it can cause unexpected results.</p>

<p>I tend to store dates and times as timestamps (using INT). The biggest drawback
is that you&#8217;re missing some of the date handling features MySQL would
otherwise provide, and it&#8217;s not clear what date and time you&#8217;re looking
at when checking out the raw data in a MySQL console or other app. The benefit is that it&#8217;s
never ambiguous. Timestamps are always based on UTC, so the chance of
making mistakes is lower.</p>

<h2>Storing time zones</h2>

<p>There are a bunch of cases where you might want to store time zones.
One example is that your users may have their own preferred time zones.</p>

<p>If you&#8217;re in need of this, never store the offset (e.g., -0500). Instead,
store the local time zone name, such as Europe/Amsterdam, Canada/Eastern, &amp;c.</p>

<p>The offset alone is ambiguous. For countries that observe DST,
the offset changes twice each year, and not necessarily on the same day. Many countries
don&#8217;t observe it at all.</p>

<p>The US and Canada recently (in 2007) shifted the day DST starts by a few weeks. In
Australia, some states observe it, and other states don&#8217;t.
Newfoundland in Canada has experimented with a 2-hour shift, and the time changes
 at 00:01. In Brazil, it&#8217;s completely crazy; they tend to
change the rules quite frequently. (The cost of everyone having to deal with this
is huge.)</p>

<p>By storing Europe/Amsterdam, if the rules change again (and they do almost every 
year, somewhere in the world), you will be prepared.</p>

<h2>Summary</h2>

<ul>
  <li>Dates and times are difficult to work with, but very interesting!</li>
  <li>Use PHP&#8217;s DateTime.</li>
  <li><em>Always</em> store dates and times in UTC.</li>
  <li>Make sure your operating system, PHP, and MySQL are all set to UTC.</li>
  <li>If you need to store time zones, use the region, but store the actual date and time in UTC.</li>
</ul>

<p>I hope this was helpful. Many programmers hate having to deal with dates and
times and time zones, but if you stick to these simple rules, it will be much easier.</p>

<h2>Developer Gift</h2>

<p>I&#8217;m embarrassed to say that, until recently, I hadn&#8217;t read a good book in several years. That all changed when I read what is hands-down my favorite book this year, <a href="http://www.amazon.com/Hyperion-Dan-Simmons/dp/0553283685">Hyperion by Dan Simmons</a>.</p>
<p>Among sci-fi geeks, it&#8217;s considered a classic. It&#8217;s a relatively easy read, and it&#8217;s not very expensive. If you do read it (or have read it), let me know what you thought!</p>]]></description>
              <link>http://phpadvent.org/2011/dates-and-times-by-evert-pot</link>
              <guid>http://phpadvent.org/2011/dates-and-times-by-evert-pot</guid>
              <pubDate>Tue, 06 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>A Stitch in Time Saves Nine</title>
              <dc:creator>Paul Jones</dc:creator>
              <description><![CDATA[<h2>The N+1 Problem</h2>

<p>It is easiest to describe the N+1 problem by example. Take a look at the following bit of PHP in a hypothetical blog app:</p>

<pre><code>&lt;?php
/**
* @var Solar_Sql_Adapter|Zend_Db_Adapter
* $sql An SQL database connection object.
*/

// 1 query to get 10 blog posts.
$stmt = 'SELECT * FROM posts LIMIT 10';
$posts = $sql-&gt;fetchAll($stmt);

// 10 queries (1 per blog post) to get
// the comments for each post
foreach ($posts as &$post) {

   $stmt = 'SELECT *
            FROM comments
            WHERE post_id = :post_id';

   $bind = array(
       'post_id' =&gt; $post['id'],
   );

   $post['comments'] = $sql-&gt;fetchAll(
       $stmt,
       $bind
   );
}
</code></pre>

<p>We have a master set of rows (the blog posts), but we need to additionally fetch many rows of comments for each blog post. To do that, we loop through the master set of rows and issue one query for each. This gets us the many rows of comments for that blog post.</p>

<p>This is the N+1 problem. In order to build up a list of 10 records, we issued 11 queries: 1 for the master set of 10 records, and then 10 more (N) queries to fetch the comments. If we also needed to get multiple tags for each post, it would be 20 more, 10 queries for the comments, and an additional 10 queries for the tags, for a total of 21 queries to build 10 records.</p>

<p>This can quickly become a performance problem even for small sets of data with many relationships. It is especially bad when you need to fetch, for example, 5 additional sets of related data for a master set of 40,000 rows. There will 1 query to get the master set of 40,000 rows, plus 5 queries per row for the related data, for 200,001 queries in total.</p>

<h2>The Solution</h2>

<p>There are at least two ways to solve the N+1 problem and reduce the number of queries dramatically.</p>

<p>One way is to write a query that joins the comments to the posts in a single massive result set. We will see repetition of the same blog posts over and over, so we would need to loop through the result set and pick out the distinct posts and retain the multiple comments for each one. There are several drawbacks:</p>

<ol>
<li><p>It&#8217;s hard to do LIMIT/OFFSET on the master set of rows that we want to retrieve.</p></li>
<li><p>We get back an oversized result from the database with lots of repeated information. To extract the related data, we need to loop through the result set in PHP and discard the repeated parts of rows, keeping track of which ones were repeated and which ones are new.</p></li>
<li><p>If we have two or more &#8220;to-many&#8221; relationships, it becomes difficult to construct the query and then pick apart the result set into your domain objects. The repetition problem from point 2 becomes exponentially more troublesome.</p></li>
</ol>

<p>Instead, I suggest a way to solve the N+1 problem that is easier to implement and more scalable across several to-many relationships. After we query for the master set of rows, we issue a single additional query to get all of the related rows in one shot, and then stitch them into the master set in a PHP loop. The following is a rewritten version of the earlier example using the query-and-stitch technique:</p>

<pre><code>&lt;?php
/**
* @var Solar_Sql_Adapter|Zend_Db_Adapter
* $sql An SQL database connection object.
*/

// 1 query to get 10 blog posts.
$stmt = 'SELECT * FROM posts LIMIT 10';
$rows = $sql-&gt;fetchAll($stmt);

// Find the ID of each post and key a 
// $posts array on them.
$posts = array();
foreach ($rows as $post) {
   $id = $post['id'];
   $posts[$id] = $post;
}

// 1 additional query to get all
// comments for all the posts.
$stmt = 'SELECT *
        FROM comments
        WHERE post_id IN (:post_ids)';

$bind = array(
   'post_ids' =&gt; array_keys($posts),
);

$rows = $sql-&gt;fetchAll($stmt, $bind);

// Stitch the comment rows into the posts.
// It is easy to find the right post for
// the comment, because we have keyed the
// posts on their ID.
foreach ($rows as $comment) {
   $id = $comment['post_id'];
   $posts[$id]['comments'][] = $comment;
}
</code></pre>

<p>We now have one additional loop in the PHP code compared to the original solution. The tradeoff is that we have saved ourselves 9 additional queries overall; we have gone from 11 (1 for the posts and 10 for the comments) to 2 (1 for the posts and 1 for the comments).</p>

<h2>Extending The Solution</h2>

<p>We can add rows from as many relationships as we like using the same technique. For example, if we also needed to fetch multiple tags in a many-to-many relationship for each post, we would do something like this:</p>

<pre><code>&lt;?php
/**
* @var Solar_Sql_Adapter|Zend_Db_Adapter
* $sql An SQL database connection object.
* 
* @var array $posts The master array of
* posts, keyed on their IDs.
*/

// 1 query to get all tags through the
// association mapping table.
$stmt = 'SELECT
           posts_tags.post_id AS post_id,
           tags.*
       FROM tags
       JOIN posts_tags
           ON posts_tags.tag_id = tags.id
           AND posts_tags.post_id IN (:post_ids)';

$bind = array(
   'post_ids' =&gt; array_keys($posts),
);

$rows = $sql-&gt;fetchAll($stmt, $bind);

// Stitch the tags into the posts.
foreach ($rows as $tag) {
   $id = $tag['post_id'];
   $posts[$id]['tags'][] = $tag;
}
</code></pre>

<p>In the original solution, we would have had a single loop in the PHP code, but a total of 21 queries. With query-and-stitch, we have 3 loops, but only 3 queries. The performance of the multiple PHP loops is practically guaranteed to be better than the performance of 21 queries.</p>

<h2>Automating the Solution</h2>

<p>The query-and-stitch technique is applicable in any context, whether a new codebase or a legacy one, using a framework or not. However, at some point we are going to want to generalize the technique so we can wrap it in a class for reuse.</p>

<p>In fact, query-and-stitch is what many ORMs do under the hood when you ask to include a relation in an <a href="http://www.basilv.com/psd/blog/2008/improving-performance-via-eager-fetching-in-hibernate">eager-fetch</a> against the master set of rows. Using an ORM is one way to automate away the N+1 problem.</p>

<p>Lots of PHP developers don&#8217;t like ORMs, though. After having developed <a href="http://solarphp.com/manual/model.intro">a robust ORM system</a> with <a href="http://procata.com">Jeff Moore</a>, I am fully acquainted with the tradeoffs involved in using ORMs. They can be opaque, ineffective, or unpredictable in edge cases, and almost always require you to learn a special way of constructing your retrieval requests. (That way can be either through a SQL-lookalike language or through a particular set of methods and informational properties.)  Even then, you may not be fully insulated from the N+1 problem, especially if the ORM <a href="http://css.dzone.com/books/practical-php-patterns/practical-php-patterns-lazy">lazy-loads</a> records in a loop where you did not eager-fetch the necessary data.</p>

<p>In contemplating the N+1 problem combined with the tradeoffs of using ORMs, it occurred to me that the core of the N+1 problem is not the SQL being used. The problem is the marshaling of the results into your domain model objects. With that in mind, I have put together an initial version of a data-marshaling package called <a href="https://github.com/auraphp/Aura.Marshal">Aura.Marshal</a> that uses the stitching technique above.</p>

<p>The package is very limited in its scope. All it does it take result sets and marshal them into domain model objects. It is completely database access layer agnostic; you can use the PHP <a href="http://php.net/mysql">MySQL functions</a>, <a href="http://php.net/pdo">PDO</a>, <a href="http://solarphp.com/class/Solar_Sql_Adapter">Solar SQL</a>, <a href="http://framework.zend.com/manual/en/zend.db.adapter.html">Zend DB</a>, or anything else. When you define your domain relationships in a type manager and then feed the types with your own query results, <a href="https://github.com/auraphp/Aura.Marshal">Aura.Marshal</a> will link up the objects for you using the stitching described above. This helps to provide an automated way of avoiding N+1 while giving us complete control over the queries being used to retrieve the data we need.</p>

<h2>Conclusion</h2>

<p>I hope the query-and-stitch technique helps you to solve your own N+1 problems. If you have comments, questions, or criticism, please feel free to <a href="http://paul-m-jones.com/archives/2152">leave a comment on my companion blog post</a>.</p>

<h2>Developer Gift</h2>

<p>I have one gift idea, in three parts. Make it an <abbr title="alcohol, tobacco, and firearms">ATF</abbr> Christmas! If the nerd in your life likes alcohol, tobacco, and firearms, he or she is sure to appreciate a <a href="http://www.famous-smoke.com/montecristo+yellow+no.+2+torpedo+5+pack+cigars/item+22926">pack of good cigars</a>, a <a href="http://www.amazon.com/dp/B005J6LQ44/">bottle of fine scotch</a>, or perhaps some <a href="http://www.luckygunner.com/">appropriately-sized ammunition</a>. The prices on these things are only going up, so get them now while you can still afford them.</p>
]]></description>
              <link>http://phpadvent.org/2011/a-stitch-in-time-saves-nine-by-paul-jones</link>
              <guid>http://phpadvent.org/2011/a-stitch-in-time-saves-nine-by-paul-jones</guid>
              <pubDate>Mon, 05 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Better Than the Rest</title>
              <dc:creator>Rob Allen</dc:creator>
              <description><![CDATA[<p>If you&#8217;ve written a web service that other clients are going to connect to, I&#8217;m willing to bet you think you&#8217;ve done a pretty good job. I would like to take a minute of your time to explore how most web services appear to the client developer. It&#8217;s not all rosy on our side of the fence, and I&#8217;m hoping that by enumerating the most common problems I come across when working with web services, your web service can avoid them.</p>

<p>Let&#8217;s start with content types and formats. There are precisely two formats that you should use to respond to a request that I send to your service: the format I indicate in the <code>Accept</code> header or the format you tell me in your documentation. What I don&#8217;t want to see is what commonly happens on two different web services that we integrate with; we send it XML messages, and in an error situation, it occasionally responds with an HTML message! This is very disconcerting, and <a href="http://php.net/simplexml">SimpleXML</a> doesn&#8217;t appreciate being asked to handle malformed HTML, either!</p>

<p>Related to this, if you are going to serve in a given format, please ensure that you provide well-formed XML/JSON/whatever. We integrate with what we affectionately call a &#8220;nearly-XML&#8221; web service. This web service returns XML that nearly parses, except for a number of wrinkles. Specifically, we have to remove some binary characters and fix some remarkably poor entity encoding. We also have to fix the character encoding of the message to UTF-8 to match the declaration. Issues like this are sloppy and do not instill confidence in your users.</p>

<p>If you are supporting a common format, then please do not provide additional restraints on the format that are not generally known. My particular pet peeve is when an XML based service expects the elements within a container to be in a particular order. If you insist on requiring a specific order of elements, please document this requirement! I&#8217;ve not yet seen this problem with JSON-based services, so I assume it&#8217;s related to particular XML parser used in some enterprise middleware components.</p>

<p>Speaking of documentation, errors need to be really well documented&#8201;&#8212;&#8201;ideally within the returned error. Your users have no idea why your service doesn&#8217;t accept the request, and they want a clear reason. They do not want a  message that says: <code>Unable to store entity [CLIENT] - Status -6</code>. This is especially useless if you don&#8217;t tell us what <code>-6</code> means. Nothing slows productivity more than wasting time trying to get a request to work when you don&#8217;t know what you&#8217;ve done wrong, so throw us poor client developers a bone and provide good error messages. A better error would be: <code>Unable to store entity [CLIENT] - Status -6: Missing NAME field</code>.</p>

<p>All of the issues that I&#8217;ve talked about in this article are really easy to get right, and they all point to a root cause, the developers of the web service have never consumed their own service. If there&#8217;s one thing I want you to take away from this article, it&#8217;s this. <em>Please</em> write an app that consumes your web service. Also, consider writing a test suite for your web service and adding a new test case for every single support ticket you have to deal with. Create a polished web service, and everyone will be talking about how awesome you are!</p>

<p>Of course, if you are feeling all smug because your web service doesn&#8217;t make any of these mistakes, I thank you. You are making the Web a better place for us all.</p>

<h2>Developer Gift</h2>

<p>As all good English people will attest, the best way to get through a long coding session is tea. Lots of tea. In that vein, may I suggest this <a href="http://www.zazzle.co.uk/keep_calm_mug-168657796888274070">excellent mug</a> as the ideal gift for your developer friends. Of course, if you haven&#8217;t yet embraced <a href="http://www.taylorsofharrogate.co.uk/item.asp?itmid=1090">good tea</a>, I expect that you could even use this mug for coffee.</p>]]></description>
              <link>http://phpadvent.org/2011/better-than-the-rest-by-rob-allen</link>
              <guid>http://phpadvent.org/2011/better-than-the-rest-by-rob-allen</guid>
              <pubDate>Sun, 04 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Reduced-Friction Deployment</title>
              <dc:creator>Chris Hartjes</dc:creator>
              <description><![CDATA[<p>I view my job as shepherding code from its inception in a Vim buffer, in a terminal session, in my development environment, until it makes it up into production in our space-age cloud app architecture. Anything less than that will result in mistakes, missed deadlines, and unfulfilled promises. It will also create unnecessary friction.</p>

<p>How can we get there? I wanted to share my thoughts on things you can do to reduce the deployment friction, even if you can&#8217;t get to continuous delivery any time soon.</p>

<h2>Identical Environments</h2>

<p>Failure to have a development environment that matches your production environment as closely as possible is the number one cause of the oft-used &#8220;unable to duplicate&#8221; response to a bug. The rise of easy-to-use virtual machine tools like <a href="http://vmware.com/">VMware</a> and <a href="http://virtualbox.org/">VirtualBox</a> means that it is easier than ever to duplicate your production environment on your desktop or laptop.</p>

<p>It also allows you to experiment with new features and work on code that can potentially alter or destroy data. Accidentally erased an entire table? No problem, just grab another copy of the virtual machine you were using and try again.</p>

<h2>Environmentally-Aware Apps</h2>

<p>If you are using third-party APIs in your app, you can often use a sandbox for testing purposes, and the real deal in production. You might also want to use separate databases for your staging and production servers. Either way, your app needs to know where it is actually running so you can control what it communicates with.</p>

<p>Web server environment variables are good for this when coupled with a registry that contains information unique to each environment where your application runs.</p>

<h2>Automated Tests</h2>

<p>Yes, I know, I know. Testing is a holy war unto itself&#8201;&#8212;&#8201;even more vicious than tabs versus spaces. Sometimes, your app is incredibly difficult to test in an automated fashion. I understand, but you do have options.</p>

<p>Your best option is to start using <a href="http://phpunit.de">PHPUnit</a> for your testing needs, as it can be run from the command line, which also means that running your tests could be triggered by a commit to your version control repository.</p>

<p>If you can&#8217;t do that, consider a tool like <a href="http://seleniumhq.com/">Selenium</a>, which can run automated tasks in a browser for you and report back its findings. With a little work, you can get Selenium to also ensure certain values are present on specific pages.</p>

<h2>Push-Button Deployment</h2>

<p>Manual deployments are full of potential problems if they are beyond issuing one command. Database changes, asset compression, minifcation of JavaScript, restarting of services&#8201;&#8212;&#8201;the list of tasks that need to be performed as part of a &#8220;normal deployment&#8221; grows longer with every passing day. Every step is an opportunity to make a mistake that could have huge implications.</p>

<p>Tools like <a href="http://phing.info">Phing</a>, <a href="https://github.com/capistrano/capistrano/wiki">Capistrano</a>, or even Bash can quickly and easily reduce your deployment process to the execution of one command.</p>

<h2>Keep Fighting the Fight</h2>

<p>Creating frictionless deployment workflows are hard, but they are worth the effort, because once you&#8217;ve reached that point, you&#8217;re able to concentrate on solving difficult problems instead of worrying about whether or not your new code is going to work this time.</p>

<h2>Developer Gift</h2>

<p>I can&#8217;t think of any programmer who wouldn&#8217;t benefit from having a copy of <a href="http://pragprog.com/the-pragmatic-programmer">The Pragmatic Programmer</a>, by Andrew Hunt and David Thomas. Mine is well-worn from its use as a reminder that while we are sometimes solving difficult problems, there are often simple solutions to them.</p>
]]></description>
              <link>http://phpadvent.org/2011/reduced-friction-deployment-by-chris-hartjes</link>
              <guid>http://phpadvent.org/2011/reduced-friction-deployment-by-chris-hartjes</guid>
              <pubDate>Sat, 03 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>More Than Just Style</title>
              <dc:creator>Laura Beth Denker</dc:creator>
              <description><![CDATA[<p><a href="http://pear.php.net/package/PHP_CodeSniffer/redirected">PHP CodeSniffer</a> is a wonderfully simple tool for implementing and enforcing a coding standard. The basic installation comes with a handful of existing coding standards, like <a href="http://pear.php.net/manual/en/standards.php">PEAR</a>. One can easily cobble together a coding standard with a subset of sniffs from any of the existing coding standards. It&#8217;s even fairly simple to write your own sniffs in the event an existing sniff just isn&#8217;t quite right.</p>

<p>Coding standards can be controversial on many levels. Many have argued over which existing standard to use. Some have entered into arguments over which aspects to pull from multiple coding standards into a new coding standard. Others have argued over conjuring a a new coding standard which often leads to mundane arguments over where to have whitespace and how many characters per line. On the other side, there have been several that have argued that all of this arguing over what to have in a coding standard is simply wasting so much time that there could not possibly be a way that implementing and enforcing a coding standard could ever help. Assuming you can settle on a coding standard, enforcing the standard on a legacy code base can be yet another hurdle.</p> 

<p>Many have traveled the path of choosing a coding standard and then attempted to enforce it on a legacy code base with PHP CodeSniffer with the very typical result of abandoning the whole notion of a coding standard due to the seemingly insurmountable number of errors.</p>

<p>The skeptics have won! There can&#8217;t be any possible benefit for spending time fixing all of these code standard violations! After all, it&#8217;s just style!</p>

<p>The general argument for having a coding standard is that having a common coding <em>style</em> will allow the programmer to focus on the problem and less on the formatting of the code.</p>

<p>Coding standards typically look like just style, but style can be helpful beyond reducing distractions while implementing new features. For example, disallowing superfluous whitespace can help keep your file history cleaner, as you will not have commits that only contain accidental changes to superfluous whitespace.</p>

<p>Coding standards are commonly referred to as style guides, but PHP CodeSniffer also has several sniffs that can save you from parse errors, like checking for duplicate property, parameter, and class names. There are other sniffs that can save you from potential runtime errors, like the sniff that detects jumbled incrementers in for loops.</p>

<p>There are also sniffs that can help you find where your code is complex and likely very buggy, like the nesting level and cyclomatic complexity sniffs.</p>

<p>Haven&#8217;t upgraded to PHP 5.3 yet? Someone has written a coding standard for that!</p>

<p>Not a fan of a particular language construct? You could write a sniff for that, too!</p>

<p>Coding standards enforced with PHP CodeSniffer can help with so much more than style, so how can we move beyond the insurmountable number of errors?</p>

<p>Start by picking some sniffs you would like to include in your coding standard, and see how many violations you have. If you have a small number of violations for a particular sniff, clean that up and enforce that sniff. If you find a sniffs with a large, but not too scary, number of violations, then consider distributing those across your team to fix by either by using a pre-commit hook or organizing a &#8220;fix-it&#8221; day.</p>

<p>Some sniffs could result in a ridiculous number of violations. This is where you will need to stop and think. Is this something worth enforcing? Did we &#8220;vote with our feet&#8221; to be doing something slightly different from this sniff? It is not a terrible thing to write your own sniff, as it is quite possible that there is some aspect of a coding standard that is already more dominate in your code than what you chose when picking out the pieces of your standard. It might be better to keep that aspect of your existing style intact rather than to modify. Also, some of the existing sniffs contain hidden subtleties that might not be for you.</p>

<p>From here, you should watch the number of violations for the currently unenforced sniffs go down, and eventually just fix the remainder and add those sniffs to your enforced coding standard. It may take awhile, but rest assured that your code base is becoming much better.</p>

<h2>Developer Gift</h2>

<p>I have two gift ideas.</p>

<p>I love to knit. It gives me something to do while watching my husband play video games on a frigid weekend morning, and it makes my subway commute more productive. I tried many times to knit with straight needles on my morning commute, but too often I would drop one of my needles and scramble to get it back. Then I discovered circular needles. I could now knit a hat a day, and really, who couldn&#8217;t afford to have an extra ski cap? Now, I have the <a href="http://www.knitpicks.com/needles/Options_Interchangeable_Zephyr_Acrylic_Circular_Knitting_Needle_Set__D90398.html">Options Interchangeable Zephyr Acrylic Circular Knitting Needle Set</a>. The acrylic tips are so light, nimble, and sharp. I am no longer dropping a needle on the train, as they are attached. An interchangeable knitting needle set is also the most cost and space efficient way to have the needle combinations needed to tackle any knitting project. You may not be a knitter (yet), but chances are you know someone who is, and it would be mighty nice of you to get them (or yourself) a set (and then ask them to make you something).</p>

<p>Knowing the difference between baking soda and baking powder is important, which is why I am glad there is a chapter for each in <a href="http://www.amazon.com/Cooking-Geeks-Science-Great-Hacks/dp/0596805888/ref=sr_1_3?ie=UTF8&#38;qid=1322758006&#38;sr=8-3">Cooking for Geeks: Real Science, Great Hacks, and Good Food</a>. Besides, cooking is more fun when you have the know-how to make it your own, rather than programmatically executing a recipe verbatim.</p>]]></description>
              <link>http://phpadvent.org/2011/more-than-just-style-by-laura-beth-denker</link>
              <guid>http://phpadvent.org/2011/more-than-just-style-by-laura-beth-denker</guid>
              <pubDate>Fri, 02 Dec 2011 00:00:00 -0500</pubDate>
            </item>
                        <item>
              <title>Because It’s Fun!</title>
              <dc:creator>Derek Sivers</dc:creator>
              <description><![CDATA[<p>Twelve years ago, computers were a mystery to me, but a friend of mine showed me how I could just go down to the computer parts store, pick out a motherboard, CPU, RAM, hard drive, power supply, &#38;c., and put it together myself. It was so empowering! Those mysterious black boxes that our lives depend on were one step less mysterious.</p>

<p>I learned how to download Linux and install it myself for free&#8201;&#8212;&#8201;then, FreeBSD and OpenBSD. Then, I was building my own servers. Now, the whole web server/Internet thing was less of a mystery. This was, again, fascinating and empowering.</p>

<p>Ten years ago, I was the founder/owner/CEO of <a href="http://cdbaby.com/">a music distribution company</a> that grew from just me to 85 employees.</p>

<p>As the company grew, I enjoyed building all of the office PCs and web servers myself. I enjoyed setting up the same FreeBSD distribution for everyone, and writing shell scripts to automate the installation of everything. It was a fun challenge, and I&#8217;d often stay until midnight setting these things up, totally &#8220;in the zone&#8221; and loving it.</p>

<p>Ten years later, I mentioned this to a friend. He said, sarcastically, &#8220;Pffft. Yeah, that&#8217;s a good use of the CEO&#8217;s time!&#8221;</p>

<p>In the moment, I laughed, but later I thought, &#8220;Well&#8230; yeah! It was my company, and I was the CEO. So, I could do whatever I wanted, and that&#8217;s what I wanted to do! What else should I be doing? Something less fun? Sitting in meetings? Why?&#8221;</p>

<p>Just this week, an investor friend asked what I&#8217;m working on now. I spun my laptop to show him a screen filled with PHP. He said, &#8220;Why are you doing this?  You can hire someone to do it!&#8221;</p>

<p>I said, &#8220;This is the only thing I love doing. Programming is pure creativity. Why would I hand off the fun stuff to someone else?&#8221;</p>

<p>It was clear that both friends were just assuming that what I <em>should</em> have been doing is whatever is the most profitable thing, as if that&#8217;s the only measure that matters.</p>

<p>Even now, I&#8217;m trying a geeky project; I&#8217;m setting up a JSON-only REST API and <a href="http://phpadvent.org/201002">requiring even my own site</a> to use only that. When I tell this to other programmers, a few have asked, &#8220;Why go to that trouble? You don&#8217;t need it!&#8221;</p>

<p>My answer is the same for everyone. &#8220;Because it&#8217;s fun!&#8221;</p>

<p>No other reason is needed.</p>

<p>Never forget that all of these things we do&#8201;&#8212;&#8201;making money, building a company, whatever&#8201;&#8212;&#8201;are all leading to the eventual goal of having enough money to do whatever we want. So, take a shortcut to that goal, and do whatever you want in the meantime. Never feel embarrassed or defensive about doing something just because it&#8217;s fun.</p>

<h2>Developer Gift</h2>
<p>I recommend any <a href="http://www.cutleryandmore.com/polder/stainless-steel-60-minute-mechanical-kitchen-timer-p116091">loud, ticking timer</a> to use with the <a href="http://www.pomodorotechnique.com/book.html">Pomodoro Technique</a>.</p>

<p>Don&#8217;t use an app. Get the actual physical ticking thing&#8201;&#8212;&#8201;it really makes a psychological difference.</p>
]]></description>
              <link>http://phpadvent.org/2011/because-its-fun-by-derek-sivers</link>
              <guid>http://phpadvent.org/2011/because-its-fun-by-derek-sivers</guid>
              <pubDate>Thu, 01 Dec 2011 00:00:00 -0500</pubDate>
            </item>
              </channel>
</rss>

