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

<channel>
	<title>Stuart Herbert On PHP</title>
	<atom:link href="http://blog.stuartherbert.com/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.stuartherbert.com/php</link>
	<description>Stuart Herbert's PHP Blog - Architecture, Code, and Hosting</description>
	<lastBuildDate>Thu, 10 May 2012 08:30:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Getting PEAR Working On Windows 7</title>
		<link>http://blog.stuartherbert.com/php/2012/05/10/getting-pear-working-on-windows-7/</link>
		<comments>http://blog.stuartherbert.com/php/2012/05/10/getting-pear-working-on-windows-7/#comments</comments>
		<pubDate>Thu, 10 May 2012 08:30:23 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[2 - Intermediate]]></category>
		<category><![CDATA[phix]]></category>
		<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=914</guid>
		<description><![CDATA[So that I don&#8217;t forget how to do this next time around. Worked for me, your mileage may vary. First step is to get a working install of PHP. Download PHP 5.4.latest ZIP file from the PHP Windows website Unpack the ZIP file into c:\php. You should end up with c:\php\php.exe Copy c:\php\php.ini-development to be [...]]]></description>
			<content:encoded><![CDATA[<p>So that I don&#8217;t forget how to do this next time around.  Worked for me, your mileage may vary.</p>
<p>First step is to get a working install of PHP.</p>
<ol>
<li>Download PHP 5.4.latest ZIP file from <a href="http://windows.php.net">the PHP Windows website</a></li>
<li>Unpack the ZIP file into c:\php. You should end up with c:\php\php.exe</li>
<li>Copy c:\php\php.ini-development to be c:\php\php.ini</li>
<li>Edit c:\php\php.ini to suit (e.g. set date.timezone)</li>
<li>Make sure you add c:\php to your system PATH (via Computer&#8217;s Advanced Properties -> Environment Variables)</li>
<li>Reboot (this is Windows, after all :)</li>
</ol>
<p>At this point, you should be able to open up a Command Prompt, and type &#8216;php -v&#8217;, and see the response &#8216;PHP v5.4.latest &#8230;&#8217; appear as expected.</p>
<p>Now for PEAR itself.</p>
<ol>
<li>Open <a href="http://pear.php.net/go-pear.phar">http://pear.php.net/go-pear.phar</a> in a browser, save this file into c:\php</li>
<li>In a Command Prompt, cd to c:\php and then run &#8220;php c:\php\go-pear.phar&#8221;</li>
<li>At the prompt, select &#8216;system&#8217;. A text menu of paths will appear</li>
<li>Fix the default path for pear.ini (option 11) to be c:\php\pear.ini</li>
<li>Fix the default folder to look inside for php.exe to be c:\php</li>
<li>Make sure the binaries folder (option 4) is c:\php</li>
<li>Check all of the other options, make sure they are prefixed with c:\php</li>
<li>Press ENTER, and you should see PEAR downloading various PEAR packages onto your system</li>
<li>Double-click the PEAR_ENV.reg file in c:\php</li>
<li>Reboot again to make sure PEAR_ENV registry entries have taken effect</li>
</ol>
<p>At this point, PEAR is installed and should be available to use in your own projects, or with something like <a href="http://phix-project.org">Phix</a>.</p>
<h3>Personal Notes</h3>
<p>Some reminders to myself for the next time I have to do this.</p>
<ul>
<li>Documentation for PHP for Windows and PEAR for Windows both seem to be out of step with current downloads.  There&#8217;s currently no Windows installer for PHP available, and the PHP .ZIP file doesn&#8217;t contain the &#8216;go-pear.bat&#8217; file.</li>
<li>You have to pay close attention to the default folders offered when running &#8216;go-pear.phar&#8217;.  They appear to use the current working directory as the prefix even when installing system-wide, except for the location of pear.ini and php.exe &#8211; neither of these defaults are sane, and must be manually changed during the install :(</li>
<li>After install, pear command doesn&#8217;t seem to be 100% compatible with its behaviour on Linux and OS X.  -D switch didn&#8217;t work, there may be other problems too that I haven&#8217;t yet found.</li>
<li>Both reboots are required &#8211; I&#8217;m not taking the piss there &#8211; for all running Windows apps to pick up the changes.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/05/10/getting-pear-working-on-windows-7/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Setting Up Sublime Text 2 For PHP Development</title>
		<link>http://blog.stuartherbert.com/php/2012/02/28/setting-up-sublime-text-2-for-php-development/</link>
		<comments>http://blog.stuartherbert.com/php/2012/02/28/setting-up-sublime-text-2-for-php-development/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 08:00:14 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=900</guid>
		<description><![CDATA[Wow. Last week&#8217;s opinion piece about switching from Netbeans to Sublime Text 2 has been the most popular blog post I&#8217;ve written for quite a while. As the interest seems to be there, I thought it would be a great idea to follow up with a post taking you step by step through how I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Wow. <a href="http://blog.stuartherbert.com/php/2012/02/20/why-ive-switched-from-netbeans-to-sublime-text-2-for-php-development/">Last week&#8217;s opinion piece about switching from Netbeans to Sublime Text 2</a> has been the most popular blog post I&#8217;ve written for quite a while.</p>
<p>As the interest seems to be there, I thought it would be a great idea to follow up with a post taking you step by step through how I&#8217;ve set up Sublime Text 2 for PHP development, and showing you some of the useful features that you get out of the box with Sublime Text 2.</p>
<p>You&#8217;ll find the details below, and as a bit of an experiment, I&#8217;ve also put the details together in a series of YouTube videos for those folks who&#8217;d prefer to see ST2 in action.  The video directly below is the first in the playlist, and I&#8217;ve also put the video for each feature separately further down.  If you like the videos, please do click the &#8216;Like&#8217; button on YouTube so that I know :)</p>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?list=PL33262F43597A9B23&amp;hl=en_US" frameborder="0" allowfullscreen></iframe></p>
<p><em>Tip: If you can&#8217;t see any YouTube videos on this page, you might need to switch off your browser&#8217;s AdBlock plugin and then reload the page.</em></p>
<h3>Install Package Control, Soda, And A Syntax Highlighting Scheme</h3>
<p>Out of the box, Sublime Text 2 is a very good text editor.  It&#8217;s so good, in fact, that I&#8217;ve seen people use it in its vanilla form perfectly happily for days and weeks before realising that it can be enhanced with third-party plugins!</p>
<p>The first plugin I recommend installing is Will Bond&#8217;s <a href="http://wbond.net/sublime_packages/package_control">Package Control</a> (<a href="http://wbond.net/sublime_packages/package_control/installation">installation instructions</a>). Package Control is a plugin that automates the job of installing and upgrading plugins.  After you&#8217;ve installed it, restart ST2, and then you&#8217;ll find a new &#8220;Package Control&#8221; menu option at the bottom of the &#8220;Preferences&#8221; menu.</p>
<p>There are over 200 community plugins currently available for ST2.  You&#8217;ll find them by going into Package Control and selecting the &#8216;Discover Packages&#8217; option.  This takes you to the community packages webpage, where you can browse or search through the available packages.  It&#8217;s worth going back and checking this page from time to time, as new packages are being added on a regular basis.</p>
<p>The next thing I normally do is reskin ST2.  This is entirely a personal preference!  Using Package Control, install the &#8216;Soda&#8217; Theme plugin; this downloads the plugin, but does not activate it.  Then, open up the &#8216;Settings &#8211; User&#8217; preferences file (this is a JSON file), and add the following to tell ST2 to use the new theme:</p>
<pre>
"theme": "Soda Dark.sublime-theme",
</pre>
<p>You&#8217;ll notice a change straight away, but will probably need to restart ST2 for it to pick up all of the new theme properly.</p>
<p>Finally, I setup syntax highlighting to suit.  ST2 ships with a number of these, and you can (if you wish) feed it any colour scheme originally created for TextMate.  I prefer to use the &#8216;Phix Color Scheme&#8217;, which is available through Package Control.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/OzqCpZeNp44" frameborder="0" allowfullscreen></iframe></p>
<h3>Editing User Preferences</h3>
<p>In ST2, nearly all of the configuration is done by creating and editing config files.  There are no user interfaces to click through, just JSON files to edit by hand.  There are a few of these files, and the basic idea is that there&#8217;s nearly always a &#8216;default&#8217; config file (which contains the defaults that ST2 or its plugins ship with), and &#8216;user&#8217; override files.</p>
<p>If you go into the Preferences menu, you&#8217;ll see a &#8216;Settings &#8211; Default&#8217; option.  This opens the default settings file that ST2 ships with.  It&#8217;s very well documented, and well worth a browse through to see if there&#8217;s anything in there that you&#8217;d like to tweak.  Don&#8217;t make changes to this file; instead, open the &#8216;Settings &#8211; User&#8217; option on the Preferences menu, and put your changes in there.  That way, your preferences will be preserved between ST2 upgrades.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/e4dVVUkupis" frameborder="0" allowfullscreen></iframe></p>
<h3>Finding Classes With The Goto Anything Pane</h3>
<p>There are two ways you can open files in ST2.  One way is to navigate through your list of folders in the Project pane on the left hand side of the screen, clicking around with the mouse and drilling down to find the file that you&#8217;re looking for.  It works &#8230; but there&#8217;s a faster alternative.</p>
<p>Hitting CTRL+P (CMD+P on the Mac) opens up the Goto Anything pane.  Here, you can type in the name of the file that you&#8217;re looking for, and in real time, you&#8217;ll see a list of matches appear.  The searching supports fuzzy matching; you can type in partial search strings, and ST2 will use them to filter out.  This is a godsend for working with projects that include vendor folders (which you might not want to search inside), and any Subversion checkouts that include trunk, branches and tags.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/6y6tRAkpS70" frameborder="0" allowfullscreen></iframe></p>
<h3>Jump To A Line Using The Goto Anything Pane</h3>
<p>Press CTRL+G (CMD+G on the Mac), and this brings up the Goto Anything pane, ready for you to type in a line number.  As you type, ST2 goes to the line number starting to form in the input box.  You can also do exactly the same by pressing CTRL+P and typing a colon at the start of the search.  (CTRL+G simply opens the Goto Anything pane and puts the colon there for you as a shortcut).</p>
<p>You can also combine this with the file search.  Hit CTRL+P and start searching for a file.  Then, at the end of your search, add a colon, and then the line number that you&#8217;re looking for.  This will take you to that line number in that file &#8211; all from the keyboard.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/5HkLoPpXGJE" frameborder="0" allowfullscreen></iframe></p>
<h3>Goto A Defined Symbol Using The Goto Anything Pane</h3>
<p>Press CTRL+R (CMD+R on the Mac), and this brings up the Goto Anything pane, ready for you to type in the name of a function or method.  As you type, ST2 narrows down the list of matching functions, methods and classes in your file.  You can do the same by pressing CTRL+P and typing an @ symbol at the start of the search.</p>
<p>You can combine this with the file search.  Hit CTRL+P and start searching for a file.  Then, at the end of your search term, add an @ sign, and then the name of the function or method that you&#8217;re looking for.  This will take you to that function or method in that file.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/Q0OtfjgnoLA" frameborder="0" allowfullscreen></iframe></p>
<h3>Coding Quicker With The Additional PHP Snippets</h3>
<p>The Additional PHP Snippets plugin [disclaimer: I'm the author of this plugin] provides a few simple text snippets to speed up everyday chores such as creating getters and setters, and add license text to the top of the file.  It is available via Package Control.</p>
<p>Pull requests (or requests for features) are most welcome.</p>
<p>To use it, inside your PHP code, simply type &#8216;php-&#8217;, and ST2 will show you a list of all of the matching snippets.  Select the snippet you want, hit TAB, and hey presto &#8211; the snippet is dropped into your code, ready for you to adapt as required.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/Ucy5ZxH3v4k" frameborder="0" allowfullscreen></iframe></p>
<h3>Creating Doc Blocks Using DocBlockr</h3>
<p>The DocBlockr plugin makes it very quick and easy to create doc blocks for your classes, attributes, and methods.  It is available via Package Control.</p>
<p>To use it, open a new doc block as normal by typing &#8216;/**&#8217; and then pressing ENTER.  The plugin will create a template doc block for you to fill out to suit.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/WaQk9QZNaOY" frameborder="0" allowfullscreen></iframe></p>
<h3>Real-Time Syntax Checking Using SublimeLinter</h3>
<p>Real-time syntax checking is something you take for granted with an IDE, and it&#8217;s available in ST2 in 2 main flavours.  I use the SublimeLinter plugin myself, and have had no trouble with it at all, but I know that some folks have had to use the sublime-lint plugin instead.  Both are available via Package Control.</p>
<p>Once installed, your code is checked in real time for syntax errors.  Lines that contain syntax errors are highlighted, and in the status bar at the bottom of the screen, you&#8217;ll see an explanation of what the error is.</p>
<p>Sometimes, the syntax error will appear to be on the wrong line &#8211; on the line below where the real problem is.  SublimeLinter uses the &#8216;php -l&#8217; command behind the screens &#8211; PHP&#8217;s built-in linter, and is simply reporting back exactly what the PHP runtime thinks is wrong.  This might puzzle you at first if you&#8217;re used to IDEs that have their own lint algorithm built in.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/5UHeh-hdYOw" frameborder="0" allowfullscreen></iframe></p>
<h3>Consulting The PHP Manual Using Goto Documentation</h3>
<p>The PHP Manual is, imho, PHP&#8217;s true killer feature: all that detailed documentation, and it&#8217;s all freely available on the web (no need to go away and buy books on the language).  Like many PHP developers, I&#8217;ve always got the PHP Manual open when I&#8217;m working.</p>
<p>The Goto Documentation plugin allows me to look up any PHP function from inside ST2.  The plugin is available via Package Control, and once installed, you need to bind it to a key before you can use it.  This is done by opening the &#8216;Key Bindings &#8211; User&#8217; option on ST2&#8242;s Preferences menu, and adding a line like the following:</p>
<pre>
{ "keys": ["f1"], "command": "goto_documentation" }
</pre>
<p>Save the file, and you&#8217;re ready to go.</p>
<p>To use it, just put your text cursor on the PHP function that you want to look up, and hit your chosen key combination.  Goto Documentation will switch to your browser, and search the PHP Manual for the function you&#8217;ve selected.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/JGtAgsGWis4" frameborder="0" allowfullscreen></iframe></p>
<h3>Handling Trailing Whitespace Using The TrailingSpaces Plugin</h3>
<p>I know it&#8217;s a small thing, but trailing whitespace annoys the crap out of me, and I&#8217;ve always been deeply frustrated with how Netbeans never reliably stripped this from files that I created or worked on.  Thankfully this isn&#8217;t a problem with ST2, and you can add the TrailingSpaces plugin to strip files in between saving them.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/9pu6eZLQydY" frameborder="0" allowfullscreen></iframe></p>
<h3>Testing Using PHPUnit</h3>
<p>The PHPUnit plugin [disclaimer: I am the plugin's author] allows you to run your unit tests right from inside ST2.  You can run the tests for just the file you&#8217;ve got open, or you can run all of your project&#8217;s unit tests in one go.  You can also switch back and forwards between your PHP code and your unit test files, and you can quickly open your project&#8217;s phpunit.xml file.</p>
<p>To use the plugin, your project needs to have either a phpunit.xml file, or a phpunit.xml.dist file.  This is a simple config file that tells PHPUnit where your tests are, which folders to include / ignore for code coverage purposes, and what reports / logs PHPUnit should create once the testing is done.  If you&#8217;re using something like Phix, you get all of this for free, and I believe that Symfony&#8217;s standard app skeleton also includes a phpunit.xml file too.</p>
<p>The plugin navigates around your project, switching from file to file, using the following algorithm:</p>
<ol>
<li>It takes the full name of your PHP class, including the namespace, and uses the PSR0 autoloader algorithm to try and find the same class with &#8216;Test&#8217; appended on the end.  If that doesn&#8217;t work, it strips off the namespace and tries again.</li>
<li>To find the phpunit.xml file, the plugin finds the test code first, and then searches each folder upwards for phpunit.xml or phpunit.xml.dist.  If that doesn&#8217;t work, it looks in a number of pre-determined locations (defined in the plugin&#8217;s settings file), and then as a last resort it searches your whole project downwards starting from the top folder.</li>
</ol>
<p>When you run your tests, the full output from PHPUnit appears in a panel at the bottom of ST2&#8242;s window &#8211; and that includes information on the full command executed, and which folder it was executed from.  To close the panel, just hit ESC.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/TceLCWRBG7M" frameborder="0" allowfullscreen></iframe></p>
<h3>Alignment Plugin</h3>
<p>This is a very simple plugin; it allows you to select some lines of code, and have all of the equals signs line up under each other.  I find that this can make code (and especially array definitions) much clearer to read, but I know that it isn&#8217;t for everyone :)</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/Gn5LC-Xj8dY" frameborder="0" allowfullscreen></iframe></p>
<h3>Software Archaeology Using CTags</h3>
<p>One of the ways that IDEs add a lot of value is that they truly understand the code you&#8217;re working on, and that allows them to offer features like &#8216;goto source definition&#8217; et al.  There&#8217;s a way you can do this in ST2, by installing the CTags plugin.</p>
<p>Once you&#8217;ve installed the CTags plugin, before you can use it, you need to go to the plugin&#8217;s website and follow the instructions there to get a suitable &#8216;ctags&#8217; command line program installed.  The plugin is a wrapper around this command&#8217;s functionality, and cannot work without it.</p>
<p>Then, the next step is to build a tags file.  This is an index of all of your code, that the plugin can use to look up classes, functions and methods so that you can quickly jump to their definition from anywhere in your project.  This is done by hitting CTRL+T and then CTRL+R, and then waiting for the &#8216;finished building&#8217; message to appear in the status bar.</p>
<p>After that, you can navigate around your code by hitting CTRL+T and then CTRL+T again.  This works particularly well for exploring code you haven&#8217;t seen before, something that I demo in the video below.</p>
<p>One last word of advice.  CTags understands the syntax of your code, but not the strategy.  It doesn&#8217;t understand the difference between trunk/ and branches/ folders, for example, or vendor/ folders.  If there&#8217;s code in there, CTags by default will index it.  This might be what you want, but if you find that it&#8217;s picking up duplicates that you&#8217;re not interested in, you&#8217;ll need to create a CTags.sublime-settings file in your User/ package folder to override the ctags_command setting and add in some exclusions.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/5j8H73iPd7k" frameborder="0" allowfullscreen></iframe></p>
<h3>What Else?</h3>
<p>There&#8217;s one notable exception that I haven&#8217;t covered here, and that&#8217;s SublimeCodeIntel.  This is a plugin that aims to bring Komodo&#8217;s autocompletion over to ST2.  It&#8217;s a great idea, but my own experience with the plugin isn&#8217;t good.  I&#8217;ve seen it installed on two different computers running the same OS and version of ST2, and it work fine on one and not work at all on the other.  I&#8217;ve seen it stop working after a new version of the plugin was released.  I&#8217;ve learned to live without it.  But do go try it out, because if it works for you, you might really like it.</p>
<p>Are there any other ST2 plugins that you use on a daily basis?  Mention them in the comments below, and I&#8217;ll check them out :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/02/28/setting-up-sublime-text-2-for-php-development/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>10 Reasons Why I&#8217;ve Switched From Netbeans To Sublime Text 2 For PHP Development</title>
		<link>http://blog.stuartherbert.com/php/2012/02/20/why-ive-switched-from-netbeans-to-sublime-text-2-for-php-development/</link>
		<comments>http://blog.stuartherbert.com/php/2012/02/20/why-ive-switched-from-netbeans-to-sublime-text-2-for-php-development/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 06:00:10 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=858</guid>
		<description><![CDATA[I&#8217;ve recently switched from using Netbeans as my PHP dev tool of choice to Sublime Text 2. Features-wise, I think Netbeans is great. During the years I used it, I never felt that there was a feature I needed that was missing at the time. But, like all the current crop of Java-based desktop IDEs, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently switched from using <a href="http://netbeans.org/">Netbeans</a> as my PHP dev tool of choice to <a href="http://www.sublimetext.com/2">Sublime Text 2</a>.  Features-wise, I think Netbeans is great.  During the years I used it, I never felt that there was a feature I needed that was missing at the time.  But, like all the current crop of Java-based desktop IDEs, it&#8217;s so damn ugly <a href="#1">[1]</a> and slow <a href="#2">[2]</a> that I&#8217;ve had enough.  I program because it&#8217;s something that I love doing, and anything that gets in the way of that &#8230; I&#8217;ve no time for any more.  So when a work colleague introduced me to Sublime Text 2, I was in the mood to give it a go, and 3 months on, I haven&#8217;t opened Netbeans once.</p>
<p>I&#8217;ll be the first to say that Sublime Text 2 isn&#8217;t for everyone.</p>
<ul>
<li><strong>It&#8217;s a beta product</strong>, which means there are some rough edges (mostly in the plugin API I feel), but it&#8217;s more than stable enough for production use.  It has crashed a couple of times, which might put some people off, but I don&#8217;t recall losing any work as a result.  File management in the project pane still needs work.  The regular dev builds occasionally break things.</li>
<li><strong>It isn&#8217;t a full-blown IDE</strong>; it&#8217;s more like the spiritual successor to TextMate, an editor that I never personally cared for.  In particular, it doesn&#8217;t support interactive debuggers, which means no Xdebug support, and there&#8217;s currently no obvious way for a plugin to add that functionality in <a href="#3">[3]</a>.</li>
<li><strong>Auto-completion isn&#8217;t anything like what you&#8217;re used to</strong>.  The built-in auto-completion is based on a mix of static knowledge of languages and fuzzy matching against what you&#8217;ve recently typed.  There&#8217;s no obvious intelligence about the code you&#8217;re working on, nor the parameters for any method or function.  These are two things that many people will deeply miss. <a href="#4">[4]</a></li>
<li><strong>It isn&#8217;t free</strong>, but you can evaluate it for free with no time limit.  If you decide to buy, it&#8217;s substantially cheaper than both <a href="http://www.jetbrains.com/phpstorm/buy/">PhpStorm</a> and <a href="http://shop.zend.com/eu/zend-studio-for-eclipse.html?src=greybox">Zend Studio</a>, and there&#8217;s no annual subscription element to the licensing.  You&#8217;re buying a license to support and encourage an independent developer, and to show your appreciation for a very nice piece of software.</li>
<li><strong>It&#8217;s a closed-source product</strong>.  You can&#8217;t fix it yourself if it breaks, and no-one can pick up the reigns if it gets abandoned. There seems to be just one guy behind it, and if anything happened to him, that&#8217;d probably be the end of the product. That said, most of the alternatives are also closed-source too.</li>
</ul>
<p>Given all of that, why have I switched?</p>
<ol>
<li><strong>Sublime Text 2 is very <em>very</em> fast</strong>.  Sublime Text 2 itself opens instantly.  Files open instantly (provided they&#8217;re not 100 megabyte test data files). In fact, everything happens instantly &#8211; even inside a virtual machine running on a 3 year old laptop.  There are no pauses for anything to be indexed, and I&#8217;ve never seen CPU usage spike &#8211; important for us untethered users and our suffering laptop batteries <a href="#5">[5]</a>. And if a plugin slows things down at all, Sublime Text 2 tells you which one is the culprit so that you can go and disable it.  I&#8217;d compare the importance of the speed difference to switching from a hard disk to an SSD.  You don&#8217;t realise how much you&#8217;re waiting for your slow Java-based IDE until you use something that&#8217;s properly fast.</li>
<li><strong>It renders fonts properly</strong> &#8211; Droid Sans Mono and Ubuntu Mono in particular both look gorgeous &#8211; and even after a long day of use, my eyes don&#8217;t feel like they&#8217;ve been scratched on the inside by sharpened kitty claws all day long <a href="#6">[6]</a>.  True story: one of my colleagues came over to ask what I was using, because he thought it looked so nice from a distance.  When was the last time anyone ever thought that about a desktop Java app?</li>
<li><strong>All of the searching is based on an extremely powerful fuzzy matching approach</strong>.  Netbeans supports regexes, which can be very handy, but most of the time when I&#8217;m looking for something, a regex is overkill but a simple string search isn&#8217;t powerful enough.  If I&#8217;ve got both a class called &#8216;IpcProcess&#8217; and &#8216;IpcProcessID&#8217;, in Sublime Text 2 I can find the &#8216;IpcProcessID&#8217; class by searching for &#8216;ipi&#8217;; I just have to type the shortest set of characters that uniquely matches what I&#8217;m looking for.  It&#8217;s much quicker than writing (or running) a regex, and soon becomes second nature.</li>
<li><strong>There&#8217;s a &#8220;goto anything&#8221; search panel which is lightning quick</strong>.  Combined with the fuzzy matching approach, I find this a godsend for working on multiple large code bases, where there may be different classes with the same base filename, or duplicate installs of a class in vendor folders, or where I&#8217;ve got both trunk and branches checked out for the same project.  It&#8217;s a killer feature, and one that has changed my workflow for the better, especially combined with my next reason.  The panel&#8217;s also like using Google Instant &#8211; you get results as you type, giving you the instant feedback you need to refine your fuzzy search.  (There is also a &#8220;goto symbol&#8221; search panel, and a &#8220;command palette&#8221; which allows you to search through the available editor commands to execute).</li>
<li><strong>Everything can be done from the keyboard</strong>.  Everything can be done from the mouse too, but I found that doing everything from the keyboard is both faster and doesn&#8217;t break the flow of what I&#8217;m working on.  This is something I didn&#8217;t appreciate until after I&#8217;d switched, but it&#8217;s a fantastic help to me when I&#8217;ve got another developer sat next to me and we&#8217;re looking at (or for) something together.  Together with the fuzzy matching, it&#8217;s like doing software archaeology with a JCB digger instead of a trowel.</li>
<li><strong>It does a great job of auto-detecting whether a file uses spaces or tabs for indentation, and how big the tab stop is</strong>.  There are days when it seems like no two files I open are consistent in how the code is indented, and it&#8217;s rare for anyone to have tagged on a modeline to give any hints.  With Netbeans, which has a rigid config-based approach to indentation, I end up playing code-formatting table tennis with the original author of the file, as we always seem to have different indentation settings.  Sublime Text 2 works out what the existing indentation approach is, and just auto-configures itself to match.  It&#8217;s a great time saver <a href="#7">[7]</a>.</li>
<li><strong>It strips trailing spaces from the ends of lines when I save my files</strong>. This has been broken in Netbeans for years!  It&#8217;s a small thing, I know, but it really annoys the crap out of me that Netbeans doesn&#8217;t get this right.  As a bonus, in Sublime Text 2 trailing spaces actually get their own setting in color schemes, so you can see exactly where they are.  In Netbeans, they&#8217;re bloody invisible :(</li>
<li><strong>There&#8217;s <a href="http://wbond.net/sublime_packages/community">a healthy ecosystem of plugins for it</a></strong> &#8211; over 200 plugins and counting &#8211; thanks to Will Bond&#8217;s <a href="http://wbond.net/sublime_packages/package_control">Package Control</a> package manager.  Will is doing a great job of making sure that each plugin is tightly focused on sorting one problem only, to keep Sublime Text 2 as flexible and adaptable as possible &#8211; something to keep in mind if you start writing plugins yourself.</li>
<li><strong>Creating new plugins is very easy</strong>. It took me just one evening to add and release the initial PHPUnit plugin, and that included the time it took to learn both Python and the plugin API from scratch.  To make an update to your plugin, simply push your changes to your master branch on GitHub.  It&#8217;s as close to frictionless as you can get.</li>
<li><strong>I can own the tool, and set it up to suit my approach to programming</strong>.  Because extending the editor is so effortless, I can automate anything that I want, to suit exactly how I want it done.  I can create snippets, intelligent macros, and full-blown plugins to suit, and I can make them as and when some new need occurs &#8211; even one-off tasks.  In this, it reminds me most of <a href="http://www.jedsoft.org/jed/">JED</a>, which was my text editor of choice back in the 90&#8242;s for exactly the same reason.  It&#8217;s the same reason folks love Vim.  (Btw, Sublime Text 2 has a Vim mode.  I haven&#8217;t tried it, so I can&#8217;t vouch for whether it&#8217;s good enough to tempt Vim users over or not).</li>
</ol>
<p>Like Netbeans, Sublime Text 2 works on OS X, Linux and Windows <a href="#8">[8]</a>, so I can use it everywhere I used to use Netbeans.  I reckon it occupies a sweet spot that makes it very well suited to scripting languages and C/C++ development, albeit minus support for interactive debuggers.  </p>
<p>At work, some of us have taken to it, and some of us haven&#8217;t.  I&#8217;m happy to recommend it to anyone who&#8217;s looking for a change.  You can take advantage of the open-ended free evaluation period, and see if it suits you or not.  It&#8217;s working for me so far, and I probably spend more time using it than any other app on any of my computers.</p>
<p>If you do like Sublime Text 2, I&#8217;d love for you to leave a comment below with your own reasons why.</p>
<h3>Footnotes</h3>
<ol>
<li><a name="1"></a>Dear Java, the 1990&#8242;s called and asked for their crappy non-aliased font renderer back. I think Windows 3.11 is missing it terribly.</li>
<li><a name="2"></a>There was a similar parallel around 20 years.  At the time, Emacs was by far the most fully-featured editor, but everyone I know chose vi because of how slow and bloaty Emacs was at the time.  It was so bad, we used to say that Emacs stood for &#8220;Eight megs and constantly swapping&#8221; (this was back in the days of 640K of RAM).</li>
<li><a name="3"></a>The lack of debugger support is, for me, the one feature that I miss every single day.</li>
<li><a name="4"></a>There is a plugin that tries to bring Komodo&#8217;s auto-completion to Sublime Text 2, but it stopped working for me before Christmas sadly.</li>
<li><a name="5"></a>It&#8217;s like when you switch from Firefox to Chrome for the first time &#8230; your laptop just gives a sigh of relief, and you don&#8217;t have to worry quite so much about how far away you are from the next convenient wall socket to recharge from.  I can easily imagine running this on a netbook, or a laptop with very aggressive CPU throttling in place &#8211; both places where a Java-based IDE would struggle.</li>
<li><a name="6"></a>I&#8217;m highly visual, and find it really tiring to spend 10-12 hours a day in front of poorly-rendered fonts.</li>
<li><a name="7"></a>Now, if only everyone just did the right thing in the first place and used spaces instead of tab characters, we wouldn’t need functionality like this … :)</li>
<li><a name="8"></a>The keybindings are different from one platform to another, and because Python isn&#8217;t a platform-agnostic language, some plugins may not work properly on Windows at first.  But most plugin authors are happy to accept pull requests with portability fixes.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/02/20/why-ive-switched-from-netbeans-to-sublime-text-2-for-php-development/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>PHPUnit Plugin For Sublime Text 2</title>
		<link>http://blog.stuartherbert.com/php/2012/02/04/phpunit-plugin-for-sublime-text-2/</link>
		<comments>http://blog.stuartherbert.com/php/2012/02/04/phpunit-plugin-for-sublime-text-2/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 18:57:52 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=845</guid>
		<description><![CDATA[Sublime Text 2 is a new cross-platform text editor that I&#8217;ve recently switched to. It&#8217;s still in public beta, but already offers better performance (and battery life!) and a better look (fonts that render properly!) than Java-based IDEs such as Netbeans. One thing it didn&#8217;t have was support for PHPUnit, so I&#8217;ve made a plugin. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sublimetext.com/2">Sublime Text 2</a> is a new cross-platform text editor that I&#8217;ve recently switched to.  It&#8217;s still in public beta, but already offers better performance (and battery life!) and a better look (fonts that render properly!) than Java-based IDEs such as Netbeans.</p>
<p>One thing it didn&#8217;t have was support for <a href="http://www.phpunit.de">PHPUnit</a>, so I&#8217;ve made <a href="https://github.com/stuartherbert/sublime-phpunit">a plugin</a>.  It&#8217;s available to install via Package Control.</p>
<h3>You Need A phpunit.xml or phpunit.xml.dist File</h3>
<p>To use this plugin, your project needs to contain either a phpunit.xml or a phpunit.xml.dist file.  This file contains all the configuration that needs to be passed to PHPUnit.  The plugin searches upwards from your code, and will favour a phpunit.xml file over a phpunit.xml.dist file if it finds both.</p>
<p>If you don&#8217;t have one, you need to go and create one now. </p>
<h3>How To Use</h3>
<p>If you have your code open in a Sublime Text 2 window, right-click inside the window to see what your options are:</p>
<p><a href="http://blog.stuartherbert.com/php/wp-content/uploads/2012/02/Context-1.png"><img src="http://blog.stuartherbert.com/php/wp-content/uploads/2012/02/Context-1.png" alt="" title="Right-Click Menu For PHPUnit" width="520" height="450" class="aligncenter size-full wp-image-846" /></a></p>
<ul>
<li><strong>Test This Class</strong> &#8211; click this option to run just the unit tests for this class.
<p>This option appears if the PHPUnit plugin can find your unit tests.  It takes the name of your class, and uses the standard PSR-0 transformation to figure out what the name of your test file should be.</p>
<p>For example, if your class is called &#8216;Phix_Project\CommandLineLib\CommandParser.php&#8217;, the PHPUnit plugin will search for a file &#8216;CommandLineParserTest.php&#8217; that&#8217;s in a folder called &#8216;Phix_Project/CommandLineLib&#8217;.
</li>
<li><strong>Open Test Class</strong> &#8211; click this option to open up your tests in Sublime Text 2.  If you already have the tests open, this will switch tabs to your tests.
<p>Again, this option only appears if the PHPUnit plugin can find your unit tests.</li>
<li><strong>Run All Unit Tests</strong> &#8211; click this option to run all the unit tests for your code.
<p>This option just points PHPUnit at your phpunit.xml or phpunit.xml.dist file.</li>
</ul>
<p>If you have your tests open in a Sublime Text 2 window, right-click inside the window to see what your options are:</p>
<p><a href="http://blog.stuartherbert.com/php/wp-content/uploads/2012/02/Context-2-Command-Palette.png"><img src="http://blog.stuartherbert.com/php/wp-content/uploads/2012/02/Context-2.png" alt="" title="Right-Click Menu Inside a Test.php File" width="520" height="450" class="aligncenter size-full" /></a></p>
<ul>
<li><strong>Run These Tests</strong> &#8211; run these unit tests, using the phpunit.xml or phpunit.xml.dist file that the PHPUnit plugin has found.</li>
<li><strong>Open Class Being Tested</strong> &#8211; open the class that these tests are for in Sublime Text 2.  If you already have the class open, this will switch tags to your code.</li>
<li><strong>Run All Unit Tests</strong> &#8211; click this option to run all the unit tests for your code.</li>
</ul>
<p>If you&#8217;re someone who prefers keyboard over mouse, then you&#8217;ll probably want to run the PHPUnit plugin commands from Sublime Text 2&#8242;s Command Palette:</p>
<p><a href="http://blog.stuartherbert.com/php/wp-content/uploads/2012/02/Command-Palette.png"><img src="http://blog.stuartherbert.com/php/wp-content/uploads/2012/02/Command-Palette.png" alt="" title="Command-Palette" width="520" height="190" class="aligncenter size-full wp-image-848" /></a></p>
<p>You get the same commands that appear on the right-click menu &#8230; the right commands will appear for the file that you&#8217;re currently editing, just as you&#8217;d expect.</p>
<p>Finally, you can also right-click on your phpunit.xml (or phpunit.xml.dist) file in the Project Sidebar, and run your unit tests using that specific config file.</p>
<h3>Helpful Snippets</h3>
<p>Like TextMate before it, Sublime Text 2 also has a handy snippets feature, where it can insert a pre-crafted block of text (or, in our case, PHP code) to speed up your coding.  I&#8217;m collecting most PHP-related snippets in my <a href="https://github.com/stuartherbert/sublime-phpsnippets">Additional PHP Snippets</a> plugin (hat-tip to <a href="http://akrabat.com">Rob Allen</a> for the inspiration for this), but the PHPUnit plugin includes a few PHPUnit-related snippets to help.</p>
<ul>
<li><strong>phpunit-testcase</strong> &#8211; will create a new test class for you to fill out.
<p>I find this handy mostly so that I don&#8217;t have to remember which class my test class has to extend :)</li>
<li><strong>phpunit-test</strong> &#8211; will create a new test method for you to fill out.</li>
</ul>
<p>To use any snippet, type its name and then press the &lt;TAB&gt; key.  Sublime Text 2 will insert the snippet, and then you can use the &lt;TAB&gt; key to cycle through any placeholders that you need to edit.</p>
<p>If you find snippets useful, please don&#8217;t forget to check out my <a href="https://github.com/stuartherbert/sublime-phpsnippets">Additional PHP Snippets</a> plugin too!</p>
<h3>Feedback, Contributions Welcome</h3>
<p>I&#8217;d love to hear how you get on with the plugin, and any ideas you might have for additional features.  And pull requests via GitHub are most welcome too!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/02/04/phpunit-plugin-for-sublime-text-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Phix 0.15 Released</title>
		<link>http://blog.stuartherbert.com/php/2012/01/31/phix-0-15-released/</link>
		<comments>http://blog.stuartherbert.com/php/2012/01/31/phix-0-15-released/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 08:00:40 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[phix]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=838</guid>
		<description><![CDATA[Phix v0.15 is now available from pear.phix-project.org. This release is dedicated to my Dad, Leslie Herbert, who passed away in December 2011 whilst I was recovering from surgery. He was always encouraging me to spend as much time as possible working on my own software, and I&#8217;m sure he&#8217;d be happy that his PC has [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://phix-project.org/">Phix</a> v0.15 is now available from <a href="http://pear.phix-project.org">pear.phix-project.org</a>.</p>
<p>This release is dedicated to my Dad, Leslie Herbert, who passed away in December 2011 whilst I was recovering from surgery.  He was always encouraging me to spend as much time as possible working on my own software, and I&#8217;m sure he&#8217;d be happy that his PC has become my new dev box for working on things like Phix.</p>
<h3>What&#8217;s New In This Release</h3>
<ul>
<li><strong><a href="https://github.com/sebastianbergmann/phploc">phploc</a> support</strong> &#8211; the &#8220;phing code-review&#8221; command now also calculates the size of your component using phploc.</li>
<li><strong>subset support</strong> &#8211; you can now do &#8220;phix php-library:init &#8211;subset=&lt;role&gt;[,&lt;role&gt; ...]&#8221; to create components that only contain some of the different file types supported by the PEAR Installer.  There&#8217;s also a &#8220;phix php-library:removeunusedroles&#8221; command if you want to strip unused roles from an existing component.</li>
<li><strong>phpunit.xml.dist support</strong> &#8211; components now use phpunit.xml.dist by default, so that you can put your own phpunit.xml in place if you ever need to override the default settings.</li>
<li><strong>src/README.md</strong> &#8211; we now drop a (hopefully helpful) README file inside the src/ folder to explain what goes where.</li>
<li><strong>misc robustness improvements to build.xml files</strong> &#8211; I&#8217;ve made some small tweaks to the build.xml file to try and catch a few error conditions and display helpful messages.</li>
<li><strong>internal debugging</strong> &#8211; &#8220;phix -d &#8230;&#8221; (which has been documented for several release now) enables internal debugging tests inside Phix and its components.  It&#8217;s mostly there for me to use, but I thought I&#8217;d mention it in case you&#8217;re testing a patch for phix before sending it to me.</li>
</ul>
<p>A big thanks to everyone who attended my workshop at <a href="http://conference.phpnw.org.uk/phpnw11/">PHPNW11</a> in October for their feedback and feature requests for this release.</p>
<h3>How To Install</h3>
<p>To install Phix, we have <a href="http://www.phix-project.org/#install">handy one-line install scripts on the Phix project homepage</a>.  And I&#8217;ve put together <a href="http://youtu.be/FqFPIoWQFPk">a screencast of how to install Phix on Ubuntu</a>.  It&#8217;s my first ever screencast, so please be gentle :)</p>
<h3>How To Upgrade</h3>
<p>To upgrade from an earlier release of Phix, please do the following:</p>
<pre>
sudo pear clear-cache
sudo pear upgrade phix/phix4componentdev
</pre>
<p>Once you&#8217;ve upgraded phix itself, don&#8217;t forget to go into each of your components, and run</p>
<pre>
phix php-library:upgrade .
</pre>
<p>to upgrade all of the skeleton files (build.xml et al) for your component.</p>
<h3>What&#8217;s Coming In Phix 0.16</h3>
<p>Windows support hasn&#8217;t happened yet, but I hopefully have a volunteer who is going to look into that during February. </p>
<p>My priority for phix-0.16 is to make it easy to build phix-based components in <a href="http://jenkins-ci.org">Jenkins</a>, based on Sebastian&#8217;s <a href="http://jenkins-php.org/">Jenkins Template</a>.  I&#8217;m doing this next because I&#8217;m not sure how much I&#8217;ve got to change things to suit Jenkins, so I&#8217;d rather get it done sooner so it&#8217;s done and out of the way.  (And I promise that I haven&#8217;t forgotten docblox support either &#8230;)</p>
<p><a href="https://trello.com/board/phix/4e705ecfd8ae22a3990013cf">Our roadmap</a> has all the details.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/01/31/phix-0-15-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comparing ContractLib to PHP&#8217;s Built-In assert()</title>
		<link>http://blog.stuartherbert.com/php/2012/01/17/comparing-contractlib-to-phps-built-in-assert/</link>
		<comments>http://blog.stuartherbert.com/php/2012/01/17/comparing-contractlib-to-phps-built-in-assert/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 08:30:28 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[2 - Intermediate]]></category>
		<category><![CDATA[phix]]></category>
		<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=818</guid>
		<description><![CDATA[One of the questions I&#8217;ve been asked after yesterday&#8217;s blog post about Phix&#8217;s ContractLib is why not just use PHP&#8217;s built-in assert() function? I think it&#8217;s a great question, and the best way to answer it is to take a look at the key differences between two solutions. Side By Side Comparison Feature assert() ContractLib [...]]]></description>
			<content:encoded><![CDATA[<p>One of the questions I&#8217;ve been asked after yesterday&#8217;s blog post about Phix&#8217;s <a href="http://github.com/stuartherbert/ContractLib">ContractLib</a> is why not just use PHP&#8217;s built-in assert() function?  I think it&#8217;s a great question, and the best way to answer it is to take a look at the key differences between two solutions.</p>
<h3>Side By Side Comparison</h3>
<table border="1">
<thead>
<tr>
<th width="20%" align="left">Feature</th>
<th width="40%" align="left">assert()</th>
<th width="40%" align="left">ContractLib</th>
</tr>
</thead>
<tbody>
<tr>
<td>Implementation</td>
<td><a href="http://svn.php.net/viewvc/php/php-src/trunk/ext/standard/assert.c?view=markup">PHP extension written in C</a> (ships as standard part of PHP)</td>
<td><a href="http://github.com/stuartherbert/ContractLib">PHP library written in PHP</a></td>
</tr>
<tr>
<td>Enable / disable execution</td>
<td>Partial (there is an overhead when disabled, but it&#8217;s low)</td>
<td>Partial (there is an overhead when disabled, but it&#8217;s higher)</td>
</tr>
<tr>
<td>Issues PHP4-style warning when tests fail</td>
<td><a href="http://uk3.php.net/manual/en/function.assert-options.php">Yes (configurable)</a></td>
<td>No (throws a ContractFailedException instead)</td>
</tr>
<tr>
<td>Terminate PHP script when tests fail</td>
<td><a href="http://uk3.php.net/manual/en/function.assert-options.php">Yes (configurable)</a></td>
<td>Only if the ContractFailedException is never caught</td>
</tr>
<tr>
<td>Quiet eval of test expression</td>
<td><a href="http://uk3.php.net/manual/en/function.assert-options.php">Yes (configurable)</a></td>
<td>No (not required; test expressions are pure PHP code, not eval() strings)</td>
</tr>
<tr>
<td>Callback on failed test</td>
<td><a href="http://uk3.php.net/manual/en/function.assert-options.php">Yes (configurable)</td>
<td>No (unwinds the stack instead by throwing ContractFailedException)</td>
</tr>
<tr>
<td>Throws Exception when tests fail</td>
<td>No (but can emulate if you write your own assert() callback method)</td>
<td>Yes (standard behaviour)</td>
</tr>
<tr>
<td>Tests are pure PHP code</td>
<td>No &#8211; <a href="http://uk3.php.net/manual/en/function.assert.php">recommended way is to pass strings into assert() to be eval()&#8217;d</a></td>
<td>Yes</td>
</tr>
<tr>
<td>Error report includes original value that failed the test</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Support for per-test custom failure messages</td>
<td>No</td>
<td>Yes &#8211; are required to provide one</td>
</tr>
<tr>
<td>Support for Old Value storage and recall</td>
<td>No (but can emulate by hand)</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<h3>The Differences Explained</h3>
<p>The key difference is one of philosophy.  assert() sits well with the PHP4 style of error reporting and handling, whereas ContractLib is firmly in favour of the OO world&#8217;s approach to reporting errors.</p>
<p>It&#8217;s a personal preference, but I think that <strong>PHP4-style errors have no place in code that has any desire to be robust</strong>.  Exceptions aren&#8217;t perfect, don&#8217;t get me wrong, but their core property of unwinding the call stack in an orderly fashion makes writing robust code much easier.  And they also carry a payload &#8211; information about what went wrong and why &#8211; which PHP&#8217;s assert() cannot provide to the same extent.  </p>
<p>It&#8217;s much quicker to debug something when there&#8217;s a record of the value that failed the test. For that reason alone, I&#8217;d always prefer something like ContractLib over the built-in assert() approach.</p>
<p>But we can&#8217;t ignore the fact that these are tests that get shipped to, and executed in, the production environment.  Unlike unit tests, adopting programming by contract will slow down your PHP code in production.  The question is: by how much?</p>
<h3>What About The Performance?</h3>
<p>I&#8217;ve done some benchmarking between the two, using the five tests listed in the final example in yesterday&#8217;s blog post.  It&#8217;s a real-world example of the kind of tests that I would look to add to code to improve robustness.</p>
<p>Here are the results I gathered, calling the tests 10,000 times in a tight loop.  The tests were run from the command line, and the times do include PHP start-up / shutdown time and the time taken to parse each test file.  I assumed a best-case scenario, where the tests would always pass.</p>
<table border="1">
<thead>
<tr>
<th align="left">Test Approach</th>
<th align="left">Time w/ Tests Disabled</th>
<th align="left">Time w/ Tests Enabled</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tests written using assert()</td>
<td>1.103s (100%)</td>
<td>5.989s (543%)</td>
</tr>
<tr>
<td>Tests written using ContractLib</td>
<td>3.055s (277%)</td>
<td>3.096s (281%)</td>
</tr>
</tbody>
</table>
<p>When tests are disabled, using assert() is much cheaper than using ContractLib today.  That&#8217;s to be expected, as assert() is written in C.  I imagine that we could get close to the same performance if ContractLib was rewritten in C as a PHP extension.</p>
<p><strong>But, when tests are enabled, assert() is much slower than ContractLib</strong>.   Why?  Because the recommended way to use assert() is to pass the test in as a string.  PHP has to convert that string into bytecode to execute, and that conversion appears to be quite expensive.</p>
<p>Given the choice, I&#8217;d rather trade things running a little slower in production for having much faster tests when I&#8217;m writing code, and that&#8217;s why I created ContractLib.  Plus I get much better information to understand why the test failed, and if I wanted to run the tests in production, I can handle their failures in a much saner way.</p>
<h3>Final Words</h3>
<p>In my experience, the time it takes to develop and ship code is normally more critical than how fast the code runs in production.  <strong>Developer time has become a scarcer resource than CPU time.</strong>  </p>
<p>Used intelligently, these kinds of tests in your code can help your team deliver quicker, because the code they are using and reusing is more robust first time around.  <strong>Programming by contract is different to, and complements, unit testing</strong> because contract tests catch errors in using the code.</p>
<p>Whether you use <a href="http://github.com/stuartherbert/ContractLib">ContractLib</a>, <a href="http://www.php.net/assert">assert()</a>, or you create your own solution, you should really consider <strong>how much it is costing you when you <em>don&#8217;t</em> use these kinds of tests</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/01/17/comparing-contractlib-to-phps-built-in-assert/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Getting Started With ContractLib</title>
		<link>http://blog.stuartherbert.com/php/2012/01/16/getting-started-with-contractlib/</link>
		<comments>http://blog.stuartherbert.com/php/2012/01/16/getting-started-with-contractlib/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 08:30:02 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[2 - Intermediate]]></category>
		<category><![CDATA[Examples]]></category>
		<category><![CDATA[phix]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=810</guid>
		<description><![CDATA[In my last blog post, I introduced ContractLib, a simple programming by contract library that I&#8217;ve created for PHP 5.3 onwards. And I promised some examples :) Installing ContractLib ContractLib is available from the Phix project&#8217;s PEAR channel. Installing it is as easy as: At the time of writing, this will install ContractLib-2.1.0. We use [...]]]></description>
			<content:encoded><![CDATA[<p>In my last blog post, I introduced <a href="https://github.com/stuartherbert/ContractLib">ContractLib</a>, a simple programming by contract library that I&#8217;ve created for PHP 5.3 onwards.  And I promised some examples :)</p>
<h3>Installing ContractLib</h3>
<p>ContractLib is available from the <a href="http://phix-project.org">Phix project&#8217;s</a> <a href="http://pear.phix-project.org">PEAR channel</a>.  Installing it is as easy as:</p>
<pre class="brush: bash; title: ; notranslate">
$ pear channel-discover pear.phix-project.org
$ pear install -a phix/ContractLib
</pre>
<p>At the time of writing, this will install ContractLib-2.1.0.  We use <a href="http://semver.org">semantic versioning</a>, so these examples will continue to work with all future releases of ContractLib-2.x.</p>
<h3>Adding ContractLib To Your Project</h3>
<p>Assuming you&#8217;re using a PSR-0 compatible autoloader, just import the Contract class into your PHP file:</p>
<pre class="brush: php; title: ; notranslate">
use Phix_Project\ContractLib\Contract;
</pre>
<h3>Adding A Pre-condition Contract To Your Method Or Function</h3>
<p>Take a trivial method like this:</p>
<pre class="brush: php; title: ; notranslate">
class ActionToApply
{
    public function appendNow($params)
    {
        $params[] = time();
    }
}
</pre>
<p>This method works fine &#8230; until someone passes a non-array as the parameter.  At that point, your code stops working &#8211; not because your code is wrong, but because someone used it in the wrong way.  This is a classic cause of buggy PHP apps.  Thankfully, it&#8217;s very easy to address using ContractLib.</p>
<p>If we were certain that the <em>$params</em> parameter was always an array, then we can keep the method itself extremely simple and clean.  We can ensure that by adding a pre-condition using ContractLib.</p>
<pre class="brush: php; title: ; notranslate">
use Phix_Project\ContractLib\Contract;

class ActionToApply
{
    public function appendNow($params)
    {
        Contract::Preconditions(function() use ($params)
        {
            Contract::RequiresValue(
                $params,
                is_array($params),
                '$params must be an array'
            );
        });

        // original method code continues here
        $params[] = time();
    }
}
</pre>
<p>Now, if someone passes in a non-array, the caller will automatically get an E5xx_ContractFailedException, which makes it clear that the fault is in the caller&#8217;s code &#8230; not your&#8217;s.</p>
<p>PHP 5.4&#8242;s upcoming support for better type-hinting is another way to catch this kind of error, but not only does ContractLib work today with PHP 5.3 (which means you don&#8217;t have to wait to migrate to PHP 5.4), but also that you can write tests for anything, not just the checking that&#8217;s built into PHP.</p>
<p>This means you can make your code much more robust, by tightening up on the quality of the parameter passed into your code by other programmers.  To extend our example, we might decide that an empty array is also unacceptable:</p>
<pre class="brush: php; title: ; notranslate">
use Phix_Project\ContractLib\Contract;

class ActionToApply
{
    public function appendNow($params)
    {
        Contract::Preconditions(function() use ($params)
        {
            Contract::RequiresValue(
                $params,
                is_array($params),
                '$params must be an array'
            );
            Contract::RequiresValue(
                $params,
                count($params) &gt; 0,
                '$params cannot be an empty array'
            );
        });

        // original method code continues here
        $params[] = time();
    }
}
</pre>
<p>The point here is that we can go <em>way</em> beyond type-hinting checks (important as they are) and look inside parameters to make sure they are suitable.</p>
<p>Here&#8217;s a real example from Phix&#8217;s <a href="http://github.com/stuartherbert/CommandLineLib">CommandLineLib</a>:</p>
<pre class="brush: php; title: ; notranslate">
use Phix_Project\ContractLib\Contract;

class CommandLineParser
{
    // ...

    public function parseSwitches($args, $argIndex, DefinedSwitches $expectedOptions)
    {
        // catch programming errors
        Contract::Preconditions(function() use ($args, $argIndex, $expectedOptions)
        {
            Contract::RequiresValue(
                $args,
                is_array($args),
                '$args must be array'
            );
            Contract::RequiresValue(
                $args,
                count($args) &gt; 0,
                '$args cannot be an empty array'
            );

            Contract::RequiresValue(
                $argIndex,
                is_integer($argIndex),
                '$argIndex must be an integer'
            );
            Contract::RequiresValue(
                $argIndex,
                count($args) &gt;= $argIndex,
                '$argIndex cannot be more than +1 beyond the end of $args'
            );

            Contract::RequiresValue(
                $expectedOptions,
                count($expectedOptions-&gt;getSwitches()) &gt; 0,
                '$expectedOptions must have some switches defined'
            );
        });

        // method's code follows on here ...
    }
}
</pre>
<p>In this real-life code, we start off by checking for basic errors first (by making sure we&#8217;re looking at the right type for each parameter), and then we follow up with more specific tests, that ensure that we have data that we&#8217;re happy to work with.  We&#8217;ve done these tests at the start of the method, so that it isn&#8217;t cluttered with error checking, which makes our code much cleaner that it might otherwise be.  And, because all the tests are in one really easy to spot block, anyone reading your code can immediately see what they have to do to meet the contract you&#8217;ve created.</p>
<p>Because these tests are just plain-old PHP code, and don&#8217;t rely on annotations or any other such nonsense, the contracts you create and enforce are limited only by your choices.</p>
<h3>But Aren&#8217;t All Those Tests Slow?</h3>
<p>They are.  PHP&#8217;s getting better and better at this, but function/method calls have always been painfully slow in PHP.  I&#8217;m afraid that if you want robust code, you can&#8217;t have it for free.  (You can in C, but that&#8217;s a topic to discuss over a decent whiskey at a conference).</p>
<p>I&#8217;ve done key two things with ContractLib to keep the runtime cost down:</p>
<ol>
<li>Contract::Preconditions() accepts a lambda function as its parameter. Your contract&#8217;s tests go inside this lambda function, and Contract::Preconditions() only calls the lambda function if contracts are enabled.</li>
<li>By default, ContractLib does not enable contracts. You have to choose to do so by calling <em>Contract::EnforceWrappedContracts()</em>.</li>
</ol>
<p>This keeps the overhead down to just one method call (to Contract::Preconditions()) when contracts are not enabled.  It isn&#8217;t as good as having no overhead, but it&#8217;s cheaper than the developer time lost trying to track down bugs in code that always assumes the caller can be trusted to do the right thing every time.</p>
<h3>Any Questions?</h3>
<p>I hope these examples have given you an idea on how to get started with ContractLib.  If you have any questions or suggestions, please let me know, and I&#8217;ll do my best to answer them.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/01/16/getting-started-with-contractlib/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Introducing ContractLib</title>
		<link>http://blog.stuartherbert.com/php/2012/01/11/introducing-contractlib/</link>
		<comments>http://blog.stuartherbert.com/php/2012/01/11/introducing-contractlib/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 08:30:04 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[2 - Intermediate]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=800</guid>
		<description><![CDATA[ContractLib is a simple-to-use PHP component for easily enforcing programming contracts throughout your PHP components. These programming contracts can go a long way to helping you, and the users of your components, develop more robust code. ContractLib is loosely inspired by Microsoft Research&#8217;s work on the Code Contracts Library for .NET. What Are Programming Contracts? [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/stuartherbert/ContractLib">ContractLib</a> is a simple-to-use PHP component for easily enforcing programming contracts throughout your PHP components. These programming contracts can go a long way to helping you, and the users of your components, develop more robust code.</p>
<p>ContractLib is loosely inspired by Microsoft Research&#8217;s work on the <a href="http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf">Code Contracts Library for .NET</a>.</p>
<h3>What Are Programming Contracts?</h3>
<p>Programming contracts are tests around functions and methods, and they are normally used:</p>
<ol>
<li>to catch any &#8216;bad&#8217; data that has been passed into the function or method from the caller, and</li>
<li>to catch any &#8216;bad&#8217; data generated by the function or method before it can be returned to the caller</li>
</ol>
<p>These are <em>pre-condition</em> and <em>post-condition</em> tests, and they are tests that either pass or fail.</p>
<h3>Why Have Programming Contracts?</h3>
<p>Two reasons: <strong>code robustness</strong> and <strong>time saved</strong>.  </p>
<p>Programming contracts catch errors early, and (unlike unit tests) they don&#8217;t just catch your errors, they catch errors made by programmers who reuse your code.</p>
<ul>
<li><em>Catching errors early</em>
<p>There is a class of bugs best described as <em>garbage in, garbage out</em>.  The &#8220;garbage in&#8221; is data that is of the wrong type, or out of range, or missing (think empty arrays, empty strings, nulls).  Often, the garbage being fed in is also garbage that has come out of a buggy function or method.</p>
<p>Simple pre-condition checks at the start of your functions and methods quickly catches garbage data before it can propagate through your code.  The more functions and methods contain pre-condition checks, the easier it becomes to catch garbage data closer to where it is being created.  This allows you to spend less time tracking down the original source of a bug, and more time writing new code.</p>
<p>These pre-conditions also greatly increase the chances of bugs in your code being caught in development, especially when combined with a healthy amount of unit testing.</p>
<p>You can also add post-conditions at the end of your functions and methods, to make sure that you&#8217;re never returning any garbage back out of your function or method.  There&#8217;s a lot of overlap between post-conditions and unit tests; the main difference is that your post-conditions will run 100% of the time, whereas your unit tests will only run when you run them and against the (often extremely limited) data you use in your unit tests.</p>
</li>
<li><em>Catching errors when code is reused</em>
<p>Unit tests are great, and a very important part of creating high-quality code.  But they&#8217;re <em>your</em> tests.  They&#8217;re written to prove that your code does what you think it does.</p>
<p>Unit tests don&#8217;t prove that someone else is reusing your code the way you meant them to.</p>
<p>And neither do integration tests, because if someone is reusing your code, integration tests are <em>their</em> tests.  Integration tests are tests to prove that they have glued their code on top of your code in a way that they are happy with.</p>
<p>Simple pre-condition checks at the start of your functions and methods are your best opportunity to test how someone else is reusing your code, and to tell them if they&#8217;re getting it wrong.</p>
</li>
</ul>
<p>Programming contracts are about building trust (just like unit tests).  Code that you can trust is normally code that is quicker to work with.  They&#8217;re really quick to write (normally far quicker than unit tests), and they can make it really quick to track down the origin of bugs in your code.</p>
<h3>Don&#8217;t Programming Contracts Make Code Stupidly Strict?</h3>
<p>An appropriate amount of strictness is a requirement of <em>all</em> high-quality code.  The trick is knowing what to be strict about.  Not strict enough, and you let in shitty data that causes your code to fail or be insecure.  Too strict, and people will think that your code is too much trouble to work with.</p>
<p>As a general rule, pre-conditions should check for:</p>
<ul>
<li>data that&#8217;s in an incorrect format</li>
<li>data that&#8217;s out of range</li>
<li>data that&#8217;s missing</li>
</ul>
<p>Post-conditions should check the same things.  They can also be used to check for data that should have been changed, but hasn&#8217;t been changed.</p>
<h3>Aren&#8217;t Programming Contracts Too Old-Fashioned For PHP?</h3>
<p>The concept has been around for decades.  As a C programmer, I first learned about programming contracts in the early 90&#8242;s, when I was writing code that had to run for months at a time with zero downtime.  We were debugging and improving code dating back from the 1980&#8242;s, and introducing programming contracts played an important role in getting to the bottom of many of the bugs that users reported.</p>
<p>PHP code (and other modern languages like Java, Ruby, Scala etc) is fundamentally similar to older languages like C, although you may not realise that this is the case.  It&#8217;s the same fundamental paradigm &#8211; data is passed into blocks of software, and blocks of software may also pass data out too.</p>
<p>The advantage we have with PHP is that our programming contracts don&#8217;t have to be as lengthy as they would for a C program, because PHP itself can enforce type checks through type hinting, and we don&#8217;t have to worry about low-level details like proper handling of null-terminated strings.</p>
<h3>Examples</h3>
<p>You can take a look at <a href="https://github.com/stuartherbert/ContractLib/tree/master/src/tests/unit-tests/php/Phix_Project/Contract">ContractLib&#8217;s unit tests</a> on GitHub.</p>
<p>I&#8217;ll post some detailed examples in my next blog post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2012/01/11/introducing-contractlib/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Phix 0.14 Released</title>
		<link>http://blog.stuartherbert.com/php/2011/10/24/phix-0-14-released/</link>
		<comments>http://blog.stuartherbert.com/php/2011/10/24/phix-0-14-released/#comments</comments>
		<pubDate>Mon, 24 Oct 2011 20:57:41 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[phix]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=790</guid>
		<description><![CDATA[Phix v0.14 is now available from pear.phix-project.org. What&#8217;s New In This Release Snapshot versions of components &#8211; not ready to release a stable version of your component, but still need to publish your component to your PEAR channel for testing? You can now set the project.snapshot property in your build.properties file, and get non-stable packages [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://phix-project.org/">Phix</a> v0.14 is now available from <a href="http://pear.phix-project.org">pear.phix-project.org</a>.</p>
<h3>What&#8217;s New In This Release</h3>
<ul>
<li><strong>Snapshot versions of components</strong> &#8211; not ready to release a stable version of your component, but still need to publish your component to your PEAR channel for testing?  You can now set the <em>project.snapshot</em> property in your build.properties file, and get non-stable packages for distribution.</li>
<li><strong>Code coverage improvements</strong> &#8211; when you run <em>phing test</em> to run your component&#8217;s unit tests and generate the code coverage report, the code coverage report now automatically picks up all of your component&#8217;s PHP code, regardless of whether there is a test for it or not.</li>
<li><strong>phpunit.xml support</strong> &#8211; phix now puts a <em>phpunit.xml</em> file inside your component, which includes all of the settings required to execute your component&#8217;s unit tests. This should help TextMate users a lot. <em>This change was requested by attendees at the <a href="http://conference.phpnw.org.uk">PHPNW11</a> conference.</em></li>
<li><strong>More hooks in build.local.xml</strong> &#8211; for every target in your component&#8217;s build.xml file, you can now add &#8220;local.&lt;target&gt;&#8221; in build.local.xml, to perform any additional steps that you want to do. <em>This feature was contributed by Martin Wernståhl</em>.</li>
<li><strong>Usability improvements</strong> &#8211; your component&#8217;s build.xml file now traps more errors than before, hopefully making it even easier to learn how to work with components.</li>
</ul>
<h3>How To Upgrade</h3>
<p>To upgrade from an earlier release of Phix, please do the following:</p>
<pre>
sudo pear clear-cache
sudo pear upgrade phix/phix4componentdev
</pre>
<p>Once you&#8217;ve upgraded phix itself, don&#8217;t forget to go into each of your components, and run</p>
<pre>
phix php-library:upgrade .
</pre>
<p>to upgrade all of the skeleton files (build.xml et al) for your component.</p>
<h3>What&#8217;s Coming In Phix 0.15</h3>
<p>Phix 0.15 is all about making sure that Phix works as well on Windows as it already does on Linux and OSX.  The feedback from the ZendCon session (which I was gutted to be unable to attend) was that there isn&#8217;t much needed, mostly setup instructions.  Once that is done, we&#8217;ll continue to support Phix on Windows just as we already do on Linux and OSX.</p>
<p><a href="https://trello.com/board/phix/4e705ecfd8ae22a3990013cf">Our roadmap</a> for Phix 0.15 has all the details.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2011/10/24/phix-0-14-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPNW11 Conference &#8211; The Other Photos</title>
		<link>http://blog.stuartherbert.com/php/2011/10/15/phpnw11-conference-the-other-photos/</link>
		<comments>http://blog.stuartherbert.com/php/2011/10/15/phpnw11-conference-the-other-photos/#comments</comments>
		<pubDate>Sat, 15 Oct 2011 07:00:22 +0000</pubDate>
		<dc:creator>Stuart Herbert</dc:creator>
				<category><![CDATA[#phpnw]]></category>
		<category><![CDATA[Conferences]]></category>

		<guid isPermaLink="false">http://blog.stuartherbert.com/php/?p=782</guid>
		<description><![CDATA[The PHP North West User Group ran it&#8217;s 4th (and largest yet!) PHP conference &#8211; PHPNW11 in Manchester last weekend. My last set of photos from PHP North West 2011 are the odd ones out, the ones that didn&#8217;t really fit into any of the other sets. I hope you&#8217;ve enjoyed my photos from the [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.phpnw.org.uk">PHP North West User Group</a> ran it&#8217;s 4th (and largest yet!) PHP conference &#8211; <a href="http://conference.phpnw.org.uk">PHPNW11</a> in Manchester last weekend.</p>
<p>My last set of photos from PHP North West 2011 are the odd ones out, the ones that didn&#8217;t really fit into any of the other sets.</p>
<p>I hope you&#8217;ve enjoyed my photos from the conference, and maybe &#8211; just maybe &#8211; they&#8217;ve made you think about going to a PHP conference somewhere near you in the near future.</p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232454716/" title="Rob Allen by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6056/6232454716_4b4e624f76.jpg" width="500" height="332" alt="Rob Allen"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6231937077/" title="Derick Rethans by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6178/6231937077_af83ecc367.jpg" width="500" height="333" alt="Derick Rethans"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232459796/" title="Jeremy Coates by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6230/6232459796_52bb651de9.jpg" width="500" height="333" alt="Jeremy Coates"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232461348/" title="So You Want To Be A Rockstar? by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6118/6232461348_eb9086b1d7.jpg" width="333" height="500" alt="So You Want To Be A Rockstar?"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232465976/" title="On The Way To The PHPNW11 Conference by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6226/6232465976_52de186fb1.jpg" width="500" height="332" alt="On The Way To The PHPNW11 Conference"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6231952563/" title="Picadilly Gardens, Manchester by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6228/6231952563_61a73a4a37.jpg" width="500" height="332" alt="Picadilly Gardens, Manchester"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232481740/" title="The Mothership Hovers by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6174/6232481740_3eb1bf05af.jpg" width="500" height="332" alt="The Mothership Hovers"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6231965563/" title="Opening The Call For Papers For PHPUK12 by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6118/6231965563_6cc983b7d3.jpg" width="500" height="332" alt="Opening The Call For Papers For PHPUK12"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232489620/" title="Cups of Tea by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6117/6232489620_1568dae1f9.jpg" width="500" height="332" alt="Cups of Tea"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6231974737/" title="All Hail Our New Wifi Overlords! by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6180/6231974737_24e387591c.jpg" width="500" height="332" alt="All Hail Our New Wifi Overlords!"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232500384/" title="Rick, Kerry, and Jenny Admire The Many Poses Of Jeremy Coates by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6118/6232500384_68ff39cd87.jpg" width="500" height="332" alt="Rick, Kerry, and Jenny Admire The Many Poses Of Jeremy Coates"></a></p>
<p><a href="http://www.flickr.com/photos/stuartherbert/6232506310/" title="Jeremy Coates - Magma Digital - PHPNW11 Organiser And Platinum Sponsor by Stuart Herbert, on Flickr"><img class="photo" src="http://farm7.static.flickr.com/6233/6232506310_d547c2dbd9.jpg" width="500" height="332" alt="Jeremy Coates - Magma Digital - PHPNW11 Organiser And Platinum Sponsor"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stuartherbert.com/php/2011/10/15/phpnw11-conference-the-other-photos/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using apc
Database Caching using apc
Object Caching 764/764 objects using apc

Served from: blog.stuartherbert.com @ 2012-05-19 02:58:50 -->
