<?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>Casey A. McLaughlin &#187; php</title>
	<atom:link href="http://www.caseymclaughlin.com/tags/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.caseymclaughlin.com</link>
	<description>Online Portfolio</description>
	<lastBuildDate>Fri, 30 Sep 2011 13:10:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Website Caching for n00bs</title>
		<link>http://www.caseymclaughlin.com/2010/10/website-caching-for-n00bs/</link>
		<comments>http://www.caseymclaughlin.com/2010/10/website-caching-for-n00bs/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 17:47:02 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[mediawiki]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php apc]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=248</guid>
		<description><![CDATA[This article describes what caching is and why it's useful.  It also provides links for how to get started setting it up on Wordpress, MediaWiki, or Drupal.  It also includes a super-cool Visio diagram.  What article is worth its salt without a Visio Diagram?]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=Website Caching for n00bs&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-10-29&amp;rft.identifier=http://www.caseymclaughlin.com/2010/10/website-caching-for-n00bs/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=Web Development"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/10/n00b.jpg"><img class="alignright size-thumbnail wp-image-255" title="Caching - You're Doing it Wrong" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/10/n00b-150x150.jpg" alt="Don't be a Caching Dummy - Read my Article!" width="150" height="150" /></a>I finally installed a caching plugin for this site, because I know that I&#8217;m so awesome that any day now, millions of beautiful women will be clamoring to visit my website at the same time.  Some things you are just sure of.</p>
<p>While I wait for that day, it makes sense to have a caching plugin anyway.  Let&#8217;s count the reasons:</p>
<ol>
<li>It&#8217;s super easy, so time investment costs almost nothing,</li>
<li>I&#8217;m on shared hosting, so every saved bit counts,</li>
<li>Caching makes everything faster even when traffic is low, and</li>
<li>I never know when I may actually write something useful, and thousands of denziens from the across the Internet will come and bring my poor little Dreamhost server to its knees.</li>
</ol>
<p>So what is caching anyway?</p>
<p><span id="more-248"></span></p>
<p><span style="font-size: medium;"><strong>The Problem</strong></span></p>
<p>Most websites are data-driven.  That&#8217;s a good thing, because without data, you don&#8217;t have content, and without content, you don&#8217;t have a very good website.  On a web server, your content can be stored basically in one of three places:</p>
<ol>
<li>A Database</li>
<li>The Hard-drive</li>
<li>The RAM</li>
</ol>
<p>The thing is, getting data from a database is much slower and requires a ton more resources than getting it from the hard drive.  Likewise, getting data from the hard drive is super slow compared to getting it from the RAM.  Here&#8217;s a handy diagram for you visually-oriented folks:</p>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/10/caching.png"><img class="aligncenter size-medium wp-image-251" title="Hierarchy of Speed" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/10/caching-300x75.png" alt="How 'puters work" width="300" height="75" /></a></p>
<p>You can&#8217;t save your content in the RAM, because it&#8217;s not permanent storage.  You could use flat-files, but then you would lose all of the security, multi-access, and other benefits that database systems provide.  So, most sites store their data in slow, but reliable and robust databases.</p>
<p>This means, every time a user wants to view a blog post or other content on your site, the web server has to connect to the database, find the content, retrieve it, and process a bunch of code to turn it into HTML and make it look pretty.  Slow.  If there are 800 raving fans accessing that blog post at the same time, the server has to perform this process 800 times &#8212; simultaneously!  And&#8230; then the site goes down.</p>
<a name="What+Caching+Does"></a><h3>What Caching Does</h3>
<p>So: Database = Slow, Robust, Reliable.  RAM = Fast, Volatile, Not permanent.</p>
<p>Can we have the good things without the bad?  Yes we can!  Caching flies in like a superhero on crack to deliver a solution that will work.</p>
<p>Basically, a cache library takes the content in your database and copies it into a flat-file or the RAM.  Then, it instructs your website to load the data from the RAM or file rather than the database when users visit your site.  This way, your server uses fewer resources for each request, but you still get to manage the data using the database, with all of its super-cool features.</p>
<p>The caveat is, if you update the data in your database, the server needs to know to also copy the data in the cache.  Fortunately, most caching systems handle these kinds details automatically.  Sometimes however, you have to manually delete and recopy the cached versions, depending on your cache system and how it is configured.</p>
<p>In most cases, the cached versions are set to expire after a certain amount of time has passed, and then regenerate with the latest fresh data in the database.  You can configure this amount of time to be 30 seconds, five minutes, eight days, or whatever.  If your users can live without <span title="Yes they can; your data is not that import. Get over yourself already">up-to-the-second data</span>, then this method of doing things won&#8217;t be a problem.</p>
<a name="RAM+Caching+vs+Hard+Drive+Caching"></a><h3>RAM Caching vs Hard Drive Caching</h3>
<p>Memory caching is faster, but the cache will have to be regenerated if the server is restarted (not a big deal, IMHO).  File caching is a slower, but will remain in-tact if the server is restarted.</p>
<p>Memory caching requires that you or your systems administrator installs extra software on the server.  Ususally<a title="Memcached Homepage" href="http://memcached.org/"> memcache</a> (free).  File caching requires that your webserver software can write files to the hard drives.  Usually involves setting file permissions in Linux.</p>
<a name="How+to+do+it+in+Wordpress%2C+Drupal%2C+Etc."></a><h3>How to do it in WordPress, Drupal, Etc.</h3>
<p>The cool thing about being a web developer in 2010 is that, if you can think of something cool, like caching your WordPress or Mediawiki installation, somebody has probably already created a tool for it and published it as open source.</p>
<a name="Prerequisites"></a><h4>Prerequisites</h4>
<p>Before you start using these cool tools, however, you need to make sure your server can handle caching.  If you&#8217;re like <a title="Netcraft Server Survey" href="http://news.netcraft.com/archives/2010/10/12/october-2010-web-server-survey.html">58.07% of websites on the Internet</a>, you use Apache to serve up web pages.  So, the following tools would be good to have already setup.</p>
<p>If you&#8217;re on shared hosting, you&#8217;ll need to make sure that your server supports these (most good ones do).  If you manage your own server, you can install them yourself.  I&#8217;ve included the Ubuntu server commands below for those of you in the latter category:</p>
<ul>
<li><strong><a title="Memcached Homepage" href="http://memcached.org/">Memcache</a></strong> (sudo apt-get install memcached php5-memcache) &#8212; This is a piece of software that runs in the background on your server and allows you to store data in the RAM.</li>
<li><strong><a title="PHP APC Homepage" href="http://php.net/manual/en/book.apc.php">PHP APC</a> </strong>(sudo apt-get install php-apc) &#8212; This is a cache tool built specifically for PHP.  It does a lot of cool speedy-uppy things for PHP that other, more general cache tools cannot.</li>
<li><strong>mod_expires</strong> (sudo a2enmod expires) &#8212; A module for Apache that allows your website to instruct browsers to cache pages and other site resources for a certain length of time before downloading them again from the server.</li>
<li><strong>mod_headers</strong> (sudo a2enmod headers) &#8212; A module for Aapche that allows your website to modify headers before they are sent to the client.</li>
<li><strong>mod_setenvif </strong>(sudo a2enmod setenvif) &#8212; A module for Apache that allows you to change the way the webserver behaves based on different criteria, such as what browser the visitor is using.</li>
<li><strong>mod_deflate</strong> (sudo a2enmod deflate) &#8212; A module for Apache that allows the webserver content to be compressed before sending it over the network; not exactly like caching, but also a performance booster.  Many caching libraries use this.</li>
<li><strong>mod_rewrite </strong>(sudo a2enmod rewrite) <strong>&#8211; </strong>A module for Apache that allows the server to rewrite requests as they come in from the client.  Useful for redirecting clients to cached versions of files without having to invoke PHP, which saves even more time.</li>
</ul>
<p>Not sure if you have these?  Don&#8217;t worry too much &#8212; most good caching libraries will let you know.</p>
<a name="Popular+Caching+Libraries"></a><h4><strong>Popular Caching Libraries</strong></h4>
<p>There are a ton of good ones; here&#8217;s a sampling:</p>
<ul>
<li><a title="SuperCache Homepage" href="http://wordpress.org/extend/plugins/wp-super-cache/">WordPress SuperCache</a> &#8212; So far as I can tell, this cache system uses files, and it helps guide you through the process of setting up your cache.  There&#8217;s even an easy mode with a simple &#8220;On/Off&#8221; switch, so it couldn&#8217;t be simpler:  Install the plugin and turn it on.</li>
<li><a title="Wordpress Total Cache Plugin" href="http://wordpress.org/extend/plugins/w3-total-cache/">WordPress Total Cache</a> &#8212; A more powerful cache tool that lets you cache to memory or files (your choice) depending on what server software you have setup.  There are a ton of settings to manipulate.</li>
<li><a title="MediaWiki Cache Documentation" href="http://www.mediawiki.org/wiki/Manual:File_cache">MediaWiki</a> &#8212; File caching is built-in and <a title="MediaWiki Cache Documentation" href="http://www.mediawiki.org/wiki/Manual:File_cache">well-documented</a>.</li>
<li><a title="Drupal's Excellent Cache and Performance Docs" href="http://drupal.org/node/627252">Drupal </a>&#8211; Also has caching built-in, and <a title="Lullabot Article" href="http://www.lullabot.com/articles/a-beginners-guide-to-caching-data">Lullabot does a better job than I would</a> explaining it.  Also, there are modules for <a title="Memcache Drupal Plugin" href="http://drupal.org/project/memcache">Memcached</a>, and <a title="APC Drupal Plugin" href="http://drupal.org/project/apc">APC</a>.</li>
<li>Frameworks &#8212; There are<a title="PHPFrameworks.com - This list is by no means exhaustive." href="http://www.phpframeworks.com/"> zillions of PHP frameworks</a>, and most of the good ones have caching baked right in.  If you&#8217;re using a framework, you&#8217;ll want to refer to your documentation.</li>
</ul>
<a name="The+End"></a><h3>The End</h3>
<p>Well, there&#8217;s your two-cent tour.  If you&#8217;re interested in learning more about speeding up websites, I recommend <a title="Website Performance - With a greyhound on the cover!" href="http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309/ref=tmm_pap_title_0">this book</a> as a good starting place.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/10/website-caching-for-n00bs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeIgniter on the Command-Line</title>
		<link>http://www.caseymclaughlin.com/2010/10/codeigniter-on-the-command-line/</link>
		<comments>http://www.caseymclaughlin.com/2010/10/codeigniter-on-the-command-line/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 14:44:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[maintenance script]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=239</guid>
		<description><![CDATA[This post describes my adventures in writing a CLI-interface for CodeIgniter and links to my source, so you can do the same!]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=CodeIgniter on the Command-Line&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-10-22&amp;rft.identifier=http://www.caseymclaughlin.com/2010/10/codeigniter-on-the-command-line/&amp;rft.language=English&amp;rft.aulast=Administrator&amp;rft.aufirst=Mister&amp;rft.subject=Web Development"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/10/syntax_error.jpg"><img class="alignright size-thumbnail wp-image-242" title="Syntax Error" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/10/syntax_error-150x150.jpg" alt="Credit: http://www.flickr.com/photos/ripton/" width="150" height="150" /></a>So, yesterday, I spent a few hours trying to create a robust command-line interface for one of my CodeIgniter applications.  I learned a lot about PHP-CLI.  I also came to remember why it&#8217;s a bad idea to <a title="Yeah, it works, but not how you'd like it to." href="http://punditkitchen.files.wordpress.com/2009/07/128926408767331749.jpg">try and fit a round peg in a square hole</a>.</p>
<p>The thing is, CodeIgniter is a great little <strong><em><span style="text-decoration: underline;">web</span></em></strong> framework.  See the key word in that sentence?  Yes, you can hack some CLI functionality in, but if you want to start doing fancy stuff like adding multiple levels of interactive menus and such, then its time to rethink what you&#8217;re doing.</p>
<p>On the other hand, there are many reasons to create a <strong><em>simple</em></strong> CLI-interface to your web application.  The main use would be for running of maintenance tasks and automated CRON scripts.  For this kind of task, it&#8217;s very easy to create a CLI entry-point for your app.</p>
<a name="How+to+Do+It."></a><h3><span id="more-239"></span>How to Do It.</h3>
<p>I started off by grabbing some <a title="Scroll down in the article to Rule number 4" href="http://net.tutsplus.com/tutorials/php/6-codeigniter-hacks-for-the-masters/">advice from NetTuts</a> and downloading <a title="Go Git the Code" href="http://github.com/philsturgeon/codeigniter-cli">Phil Sturgeon&#8217;s excellent CLI library</a>.</p>
<p>In the same folder as the main <em>index.php </em>file, I created another file named <em>entry.php</em> to serve as my CLI entry to the application.  That file looks like:</p>
<p><script src="http://bitbucket.org/caseyamcl/snippets/src/11525f389fb7/ci-cli/entry.php?embed=t"></script> Notice that I am accepting command-line arguments.  The above code will halt execution and exit if any unknown command-line arguments are given.  It assumes the first non-switch command line argument is the action the user wants to run.  It automatically prepends the &#8220;utils&#8221; controller to the route, thereby sandboxing CLI access to a single controller.  The controller can do whatever you want.  Here&#8217;s a small example wherein I present a main menu if no route was specified when the user runs the CLI interface:  <script src="http://bitbucket.org/caseyamcl/snippets/src/11525f389fb7/ci-cli/controller.php?embed=t"></script></p>
<p>Notice the main menu!  The design goal for the Controller was for the main menu <em>index</em> method to be interactive, but every other method to be able to run unattended if parameters are sent, otherwise to display prompts.</p>
<p>I also made some heavy modifications and additions to the CLI.php library, adding the ability to run any form_validation validation function against command-line inputs (w00t), adding the ability to display view files easily, and adding a few other helper method here and there.</p>
<p>The code is too long to display in this post, but here&#8217;s a link to the <a title="The CLI Library source" href="http://bitbucket.org/caseyamcl/snippets/src/tip/ci-cli/CLI.php">file source on Bitbucket</a>.</p>
<a name="Wrap-Up"></a><h3>Wrap-Up</h3>
<p>It&#8217;s definitely not a good idea to attempt a full, robust, multi-level CLI interface for your CodeIgniter application, but this framework will help you setup a simple, even slightly-interactive CLI interface to make running maintenance tasks and providing basic tools easier for your CLI users.</p>
<p>The repository with all of the code is available on my <a title="CodeIgniter CLI on Bitbucket" href="http://bitbucket.org/caseyamcl/snippets/src/tip/ci-cli/">Bitbucket page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/10/codeigniter-on-the-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing with Asynchronous PHP Processing</title>
		<link>http://www.caseymclaughlin.com/2010/09/playing-with-asynchronous-php-processing/</link>
		<comments>http://www.caseymclaughlin.com/2010/09/playing-with-asynchronous-php-processing/#comments</comments>
		<pubDate>Fri, 24 Sep 2010 14:16:02 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[asynchronous]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[maintenance script]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php-cli]]></category>
		<category><![CDATA[queues]]></category>
		<category><![CDATA[queuing]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=225</guid>
		<description><![CDATA[In this post, I present a concept for creating a worker-process for asynchronous job queue processing in PHP.]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=Playing with Asynchronous PHP Processing&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-09-24&amp;rft.identifier=http://www.caseymclaughlin.com/2010/09/playing-with-asynchronous-php-processing/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=Web Development"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/09/page_load_dog.jpg"><img class="alignright size-thumbnail wp-image-230" title="Page Load Dog (credit http://www.flickr.com/photos/konszvi/4218539270/sizes/z/)" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/09/page_load_dog-150x150.jpg" alt="Picture Credit: konszvi at Flickr" width="150" height="150" /></a>A subject that has intrigued me lately is this topic of asynchronous PHP processing.  The idea is you have a web application that includes a task which takes a long time, like, say processing video files or sending mass emails.  Your users should be able to click a button, get a notification that their job is waiting to be processed, and then go about their business.</p>
<p>I&#8217;ve run across all sorts of <a title="Beanstalkd is cool" href="http://kr.github.com/beanstalkd/">really</a> <a title="Memcache Queue. Sweet!" href="http://memcachedb.org/memcacheq/">cool</a> <a title="I watched a presentation about this at TekX Chicago" href="http://gearman.org/">queuing</a> <a title="RabbitMQ - Good stuff." href="http://www.rabbitmq.com/">technologies</a>, all of which have PHP libraries.  So creating and managing job queues was no problem for me.  My confusion was how to setup a worker script to process those queues.<span id="more-225"></span></p>
<p>There is absolutely no way to get around the fact that you will need at-least two distinct, simultaneous processes running on your server in order to make this happen.  The process that initiates the queue jobs is presumably Apache (or whatever webserver you like).  The second process runs in the background, and it just sits and waits for jobs and processes them as they come in.</p>
<p>Of course, the only way to have a process continually listening for jobs on a Linux server is for it to be a <a title="Wikipedia will edumacate you about daemons." href="http://en.wikipedia.org/wiki/Daemon_(computer_software)">daemon</a>.  And, of course, unless you are a system administrator with root privileges, <a title="Here is how to do this in PHP, by the way (love this article)." href="http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/">setting up a reliable daemon</a> is not really an option.  So, if you are using a shared hosting provider, you are kind of out-of-luck.</p>
<p>Or, are you?</p>
<p>I&#8217;ve been toying with one way to make it happen using CRON, MySQL, and PHP-CLI, all of which <em>good</em> shared hosting providers allow you to use.  The idea is this: Every minute, a cron-task spawns a PHP-CLI script.  The script is smart enough to see if prior instance of itself is still running, and if not, it processes the job queue.  The queue can be a simple MySQL database table, or something fancier like a Beanstalkd queue or some implementation of <a title="I haven't used Zend Queue, but it looks pretty spectacular." href="http://framework.zend.com/manual/en/zend.queue.html">Zend_queue</a>.</p>
<p>Here&#8217;s how the script would run:</p>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/09/async_cron.png"><img class="aligncenter size-medium wp-image-227" title="Asynchronous Processing with CRON" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/09/async_cron-300x191.png" alt="Asynchronous Processing with CRON" width="300" height="191" /></a></p>
<p>And, below is really rough example of how I might begin to implement this in PHP, with logging thrown in.  I&#8217;m sure there are ways to tweak this, or there may already be libraries out there that do the same thing better; anybody care to chime in?</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">#!/usr/bin/php -q
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/*
 * CRON Command-Line Processor for job queues...
 *
 * Requirements:
 *  1. *nix-based system
 *  2. Cron
 *  3. Shell access
 *  4. MySQL
 */</span>
<span style="color: #666666; font-style: italic;">// Implement by setting permissions on this script to exeuctable, and adding</span>
<span style="color: #666666; font-style: italic;">// by adding the following to your crontab: */ </span>
<span style="color: #666666; font-style: italic;">// */1 * * * * /path/to/this/script.php &gt;/dev/null 2 &gt;&amp; 1</span>
&nbsp;
&nbsp;
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'CRON_PROCESS_LOGFILE'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/path/to/logfile.log'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'CRON_PROCESS_LOCK_FILE'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/path/to/lockfile.lock'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//------------------------------------------------------</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Cron_process
<span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//Log that we're getting started.</span>
		Cron_process<span style="color: #339933;">::</span><span style="color: #990000;">log</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Attempting to start cron_process of job queue...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Check to see if a prior instance of the process is already running..</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$my_special_database_connector_class</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT `status` FROM `cron_process_status`;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">row</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'in-process'</span>
				OR <span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOCK_FILE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			Cron_process<span style="color: #339933;">::</span><span style="color: #990000;">log</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Aborted processing.. Prior job already running'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
		<span style="color: #666666; font-style: italic;">//Create a lockfile and indicate in the database that the process is started..</span>
		<span style="color: #000088;">$my_special_database_connector_class</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;UPDATE `cron_process_status` SET `status` = 'in-progress';&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOCK_FILE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #990000;">touch</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOCK_FILE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$fp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOCK_FILE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">flock</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> LOCK_EX<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">fputs</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'cron_process_began_'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">fflush</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Process the jobs using whatever queue technology you want.</span>
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$my_special_queue_adapter_class</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get_number_of_pending_jobs</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #666666; font-style: italic;">// *****************</span>
			<span style="color: #666666; font-style: italic;">// HERE is where the magic happens!!</span>
			<span style="color: #666666; font-style: italic;">//  All the code for processing the job goes</span>
			<span style="color: #666666; font-style: italic;">//  right in here..</span>
			<span style="color: #666666; font-style: italic;">// *****************</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Clear the lockfile and mark the job complete in MySQL</span>
		<span style="color: #000088;">$my_special_database_connector_class</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;UPDATE `cron_process_status` SET `status` = 'idle';&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #990000;">flock</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> LOCK_UN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">unlink</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOCK_FILE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Log that we're done</span>
		Cron_process<span style="color: #339933;">::</span><span style="color: #990000;">log</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Succesfully ran the cron_process. Exiting...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//All done!</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//------------------------------------------------------</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> init_logfile<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">is_writable</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOGFILE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">&quot;Cannot write cron process logfile.  Directory &quot;</span> <span style="color: #339933;">.</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOGFILE<span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; is not writable.  Check permissions&quot;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">touch</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOGFILE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">&quot;Cannot write to cron process logfile.  Check permissions.&quot;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//------------------------------------------------------</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">log</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$msg</span><span style="color: #339933;">,</span> <span style="color: #000088;">$level</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'info'</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$str</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-M-d H:m:s'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; - <span style="color: #006699; font-weight: bold;">$level</span> - <span style="color: #006699; font-weight: bold;">$msg</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">file_put_contents</span><span style="color: #009900;">&#40;</span>CRON_PROCESS_LOGFILE<span style="color: #339933;">,</span> <span style="color: #000088;">$str</span><span style="color: #339933;">,</span> FILE_APPEND<span style="color: #339933;">,</span> LOCK_EX<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">// Processing starts here..</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Initial Checks</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">php_sapi_name</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'cli'</span> OR <span style="color: #339933;">!</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REMOTE_ADDR'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This script can be run only from the command line!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Check to ensure we can write to a logfile.</span>
<span style="color: #000088;">$init_result</span> <span style="color: #339933;">=</span> Cron_process<span style="color: #339933;">::</span><span style="color: #004000;">init_logfile</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$init_result</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #009900;">&#41;</span>
	<span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$init_result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Include any boostrap files</span>
<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/path/to/any/bootstapfiles/my_special_db_class_and_others.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
Cron_process<span style="color: #339933;">::</span><span style="color: #004000;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">/* EOF: cron_async.php */</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/09/playing-with-asynchronous-php-processing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updated my Projects!</title>
		<link>http://www.caseymclaughlin.com/2009/12/updated-my-projects/</link>
		<comments>http://www.caseymclaughlin.com/2009/12/updated-my-projects/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 22:51:08 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[announcement]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[this site]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=153</guid>
		<description><![CDATA[I've updated my CodeIgniter projects listed on this site finally!]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=Updated my Projects!&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2009-12-22&amp;rft.identifier=http://www.caseymclaughlin.com/2009/12/updated-my-projects/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=General"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/lazy.gif"><img class="alignright size-thumbnail wp-image-155" title="lazy" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/lazy-150x150.gif" alt="Lazy funny picture" width="150" height="150" /></a>As a Christmas Holiday present to those of you that are using my CodeIgniter tools, <em>CI-UserTracking</em> and <em>GeSHi for CI</em>, I did something very philanthropic: I updated them and tested them on the latest version of CodeIgniter.</p>
<p>Oh, and I also fixed the links&#8230;</p>
<p>..and I put them in their very own Google Code pages, so you can peruse the source code, download from Google servers, and leave comments and tickets for yours truly.</p>
<p>AND.. as your Hanukkah/New Years/Participation gift, I also have added a brand new CodeIgniter project that I&#8217;m working on called <em><a title="CI Headstart Google Code Page" href="http://code.google.com/p/ciheadstart/">CI Headstar</a>t</em> with all kinds of helpers, libraries, and other goodies to help speed up development even more.  Roll on over to the <a title="The Code Page -- It's new too! Yay." href="http://www.caseymclaughlin.com/code/">Code page</a> to check it all out.</p>
<p>Now that Christmas break is upon us, and I since I work for a University that gives employees like a bazillion days off each December, I hope to clean these up even more and provide some quality documentation.</p>
<p>Happy Holidays from me to you,</p>
<p><img class="size-medium wp-image-154 alignnone" title="My Signature" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/My-Signature-300x82.gif" alt="Casey McLaughlin (signature)" width="300" height="82" /></p>
<p>PS &gt;&gt; If anybody is interested in contributing code to these projects, <a title="Contact Form -- I swear it goes straight to my Gmail!" href="http://www.caseymclaughlin.com/contact/">let me know</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2009/12/updated-my-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Biting the Distributed Development Bullet</title>
		<link>http://www.caseymclaughlin.com/2009/12/make-codeigniter-svn-friendly/</link>
		<comments>http://www.caseymclaughlin.com/2009/12/make-codeigniter-svn-friendly/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 20:15:46 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[project management]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=129</guid>
		<description><![CDATA[You're a dummy for not using version control.  If I can do it, anybody can.]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=Biting the Distributed Development Bullet&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2009-12-21&amp;rft.identifier=http://www.caseymclaughlin.com/2009/12/make-codeigniter-svn-friendly/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=Web Development"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/programmer.jpg"><img class="alignright size-thumbnail wp-image-131" title="programmer" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/programmer-150x150.jpg" alt="Will Code for Food" width="150" height="150" /></a>Like most development n00bs, after I started using version control, I never looked back.  And <a title="Stack Overflow Thread" href="http://spedr.com/k1z1">neither should you</a>.</p>
<p>It required me to change the whole way that my office operated, though.  See, the way that we were doing things before seemed so simple; we just edited files and shouted at each other if we collided in our editing.  As it turns out, this was a bad thing, and there have been better alternatives around way longer than I&#8217;ve even been in this business.</p>
<p>But like most crotchety, over-egotistical developer-types it took a while for me to come around.  Here&#8217;s a brief history of my flirtations and eventual commitment to version control.</p>
<a name="Our+Blissful%2C+Youthful+Ignorance"></a><h3><span id="more-129"></span>Our Blissful, Youthful Ignorance</h3>
<p>This wasn&#8217;t really that long ago&#8230;</p>
<div id="attachment_139" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/Workflow-SSH.png"><img class="size-medium wp-image-139" title="The Old Workflow" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/Workflow-SSH-300x237.png" alt="The old, SSH-based Workflow" width="300" height="237" /></a><p class="wp-caption-text">1..2..3... Easy Peasy Japanesey.. and stupid.</p></div>
<p>We would all work directly on the files directly on our development server.  We would sit down, SSH into the server using our favorite editor and code away, never thinking of change management, reverting back to old versions, or who would be responsible for what.  Conflict resolution seemed easy&#8230; if I was editing a file named<em> welcome.php</em>, I would simply shout across the room, &#8220;Hey Mike&#8211;don&#8217;t work on <em>welcome.php</em> right now, or I&#8217;ll have to beat you!&#8221;.</p>
<p>Our revision control system consisted of me creating and storing weekly backups of the entire database and file system.  If we made a change that killed the system, we&#8217;d simply either lose that week&#8217;s work or spend hours debugging it.  It was all gloriously simple.</p>
<a name="Version+Control+Puberty+%26%238212%3B+The+Angsty+Years"></a><h3>Version Control Puberty &#8212; The Angsty Years</h3>
<p>One day, I decided to implement Subversion, mainly because other developers were sneering at me and telling me I was a dummy.  And while I didn&#8217;t want to be a dummy, the whole thing seemed overly complicated.  Why would I want to increase complication when everything was working so simple?  I also had some fundamental issues with this new version control idea:</p>
<ul>
<li>First off, everybody has to have to get their own copy of the entire file set.  Bad!  Doom! Insecure! I have to trust my developers with the codebase? ::Gasp::</li>
<li>Secondly, what do you mean that developers can&#8217;t see their changes on the server immediately upon commit without some hacked hook system?  This means they&#8217;ll have to run <a title="Wikipedia LAMP" href="http://en.wikipedia.org/wiki/LAMP_%28software_bundle%29">LAMP</a> on their local boxes, too!  Geez.. now we have to have local dev environment setup procedures, too..</li>
<li>Finally, SVN requires management of its own.  You know.. backing up, securing access, and generally managing.  More overhead and more complication!</li>
</ul>
<p>Grudgingly, in order to remove the &#8220;dummy&#8221; label from my operations, I implemented Subversion.  It was difficult at first to understand how it would fit easily into our procedures, but with some <a title="Subversion Book - Basic Work Cycle (a very helpful chapter)" href="http://svnbook.red-bean.com/en/1.5/svn.tour.cycle.html">very helpful free online material</a>, we started using it.</p>
<p>And sure, I <em>did</em> have to write procedures for setting up local dev environments AND install a subversion clients AND manage a <a title="Hands Down, VisualSVN is the easist-to-use SVN Server for Windows" href="http://www.visualsvn.com/server/">repository server</a>, but you know what?</p>
<p>All of that stuff was way worth it.</p>
<a name="All+Grown-up+Now"></a><h3>All Grown-up Now</h3>
<p>Let me repeat that: whatever frustrations version control causes, they are all worth it.</p>
<p>After being SVN disciples for a while now, our development procedures have matured.  Here&#8217;s how we do things:</p>
<div id="attachment_137" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/Workflow-SVN.png"><img class="size-medium wp-image-137" title="SVN Workflow" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/12/Workflow-SVN-300x242.png" alt="The way we do things now" width="300" height="242" /></a><p class="wp-caption-text">The way we do things now.. Much better!</p></div>
<p>I&#8217;ve since tried other VCS systems like <a title="Mercurial Homepage" href="http://mercurial.selenic.com/">Mercurial</a>, <a title="Git Homepage" href="http://git-scm.com/">Git</a>, and <a title="Bazaar Homepage" href="http://bazaar.canonical.com/en/">Bazaar</a>, but have not found any compelling reason to switch.   Either way, using version control has saved our sorry butts on more than one occasion and has made life easier in about 1,001 ways.</p>
<p>As a bonus, it has also forced us to use better procedures and generate better development documentation, which is amazing, because we&#8217;re pretty lazy.  Now if only we could find a tool to better force us to behave when it comes to unit testing&#8230;</p>
<p>Well, that&#8217;s my story.  If I&#8217;ve inspired you to use VCS, hooray!  <a title="Awesome SVN Primer I found on the front page of Google search" href="http://www.snipe.net/2009/03/getting-started-with-subversion/">Here&#8217;s a helpful place to get started</a>.  If not, you&#8217;re a dummy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2009/12/make-codeigniter-svn-friendly/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Teaching PHP: Course Curriculum</title>
		<link>http://www.caseymclaughlin.com/2009/08/teaching-php-course-curriculum/</link>
		<comments>http://www.caseymclaughlin.com/2009/08/teaching-php-course-curriculum/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 20:11:31 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[IT Management]]></category>
		<category><![CDATA[curriculum]]></category>
		<category><![CDATA[instruction]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[teaching]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=108</guid>
		<description><![CDATA[The problem, succinctly stated, is: How do you best organize 14 weeks of study to teach PHP to a group of motivated College students?]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=Teaching PHP: Course Curriculum&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2009-08-03&amp;rft.identifier=http://www.caseymclaughlin.com/2009/08/teaching-php-course-curriculum/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=IT Management"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2009/08/php-sauce.jpg"><img class="alignright size-full wp-image-110" title="php-sauce" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/08/php-sauce.jpg" alt="php-sauce" width="139" height="150" /></a>The problem, succinctly stated, is: <strong>How do you best organize 14 weeks of study to teach PHP to a group of motivated College students?</strong></p>
<p>I know they must be pretty motivated, because they&#8217;re signing up for the class despite the fact that it starts at 8 am.</p>
<p>This Fall, I will  be teaching a course in Web Application Development at FSU.  The topic will be server-side scripting, and the focus will be PHP.  Since I&#8217;ve taught this course before, developing the curriculum won&#8217;t take months, but I am nevertheless spending a fair amount of time updating and tweaking for the next go-around.</p>
<p><span id="more-108"></span></p>
<p>A quick <a title="Google Search for &quot;Teaching PHP&quot;" href="http://spedr.com/xyd0">Google Search for &#8220;Teaching PHP&#8221;</a> brings up only a few relevant links, mostly message board discussions.  &#8220;Server Side Scripting Curriculum&#8221; doesn&#8217;t return much either.  Likewise, <a title="WaSP Web Standards Project" href="http://interact.webstandards.org/">WaSP</a> have not yet published their recommended server-side scripting course recommendations.</p>
<p>So, I&#8217;ve had to come up with a lot of the course unilaterally.  The learning objectives are as follows:</p>
<p>By the end of the course, students will understand:</p>
<ul>
<li>Basic programming skills</li>
<li>Web application development principles</li>
<li>How to find and use PHP resources on the Internet</li>
<li>How to manage tasks, bugs, and revision control mechanisms for web projects</li>
</ul>
<p>By the completion of this course, students will be able to:</p>
<ul>
<li>Program and deploy simple scripts in PHP</li>
<li>Process web-based input and output in PHP</li>
<li>Build multi-file PHP applications</li>
<li>Connect PHP applications to a database</li>
<li>Design a simple dynamic website using PHP, MySQL, HTML, and CSS</li>
</ul>
<p>After a few iterations of course development, here are the topics I have planned to discuss, in order, thus far:</p>
<ul>
<li>The current &#8220;State of the Internet&#8221;</li>
<li>How the technology works &#8211; Web servers and clients</li>
<li>Eclipse setup and good  practices for personal workflow</li>
<li>PHP basics &#8211; Syntax, variables, arrays, functions, iterators, etc.</li>
<li>Form processing (GET/POST)</li>
<li>Database integration</li>
<li>Multi-file application organization</li>
<li>Classes and objects</li>
<li>MVC frameworks</li>
<li>Revision control and associated workflow</li>
<li>Basic management: Ticket and bug tracking</li>
<li>Web Services &#8211; SOAP and RPC</li>
<li>XML integration</li>
<li>Comprehensive application organization</li>
</ul>
<p>That&#8217;s <em>a lot</em> of information.  Fortunately the students will have object-oriented experience AND database experience.  So, we should be able to leap off the cliff quickly and into the world of iterators, encapsulation, and inheritance.</p>
<p>I&#8217;ll post the week-by-week calendar when I finalize it, which necessity dictates will be very soon.  Feel free to grab it and use it for your own courses, or <a title="Contact Me Form" href="http://www.caseymclaughlin.com/contact/">tell me</a> what I can improve on.</p>
<p><strong>UPDATE:</strong> The course calendar and other details are live online at <a title="LIS4368 Course Website" href="http://lis4368.cci.fsu.edu">http://lis4368.cci.fsu.edu</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2009/08/teaching-php-course-curriculum/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CodeIgniter Preflight Checker</title>
		<link>http://www.caseymclaughlin.com/2009/06/codeigniter-preflight-checker/</link>
		<comments>http://www.caseymclaughlin.com/2009/06/codeigniter-preflight-checker/#comments</comments>
		<pubDate>Fri, 26 Jun 2009 18:16:07 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[portability]]></category>
		<category><![CDATA[portable]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=84</guid>
		<description><![CDATA[This post builds on last week's discussion of how to make an application portable by demonstrating how to implement a "pre-flight" check before your application runs.]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=CodeIgniter Preflight Checker&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2009-06-26&amp;rft.identifier=http://www.caseymclaughlin.com/2009/06/codeigniter-preflight-checker/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=Web Development"></span>
<p><a href="http://www.flickr.com/photos/mike_miley/2996159793/"><img class="alignright size-thumbnail wp-image-86" title="preflight_check" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/06/preflight_check-150x150.jpg" alt="preflight_check" width="150" height="150" /></a>In <a title="Last Post: Making PHP Applications Portable" href="http://www.caseymclaughlin.com/2009/06/making-php-applications-portable/">my last post</a>, I discussed do&#8217;s and don&#8217;ts for making a PHP application portable.  This week, I will show you how to create a preflight checker in the <a title="CodeIgniter Homepage" href="http://www.codeigniter.com">CodeIgniter PHP framework</a> to ensure that an environment will support your application.</p>
<p><span id="more-84"></span></p>
<p><em>Note: This article assumes that you already have a working CodeIgniter application setup.  If you are interested in getting started with CodeIgniter, there are some <a title="CodeIgniter Video Tutorials" href="http://codeigniter.com/tutorials/">really</a> <a title="CodeIgniter Official User Guide" href="http://codeigniter.com/user_guide/">great</a> <a title="Net Tuts &quot;Getting started with CodeIgniter&quot; Article" href="http://net.tutsplus.com/videos/screencasts/easy-development-with-codeigniter/">tutorials </a>on the web.  If you&#8217;re not using CodeIgniter, skip to the &#8220;What to Check&#8221; section below for a general idea of how to apply this to PHP apps in general.</em></p>
<a name="Setting+up+the+Hook"></a><h2>Setting up the Hook</h2>
<p>The best way to setup a preflight checker is to create a hook.  Make sure that you <a title="CodeIgniter Hooks Documentation" href="http://codeigniter.com/user_guide/general/hooks.html">enable hooks</a> in your main configuration file before getting started.  We&#8217;ll be setting up a pre-system hook, so add the following code to your <em>application/config/hooks.php</em> file:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">/*Preflight Check Hook*/</span>
<span style="color: #000088;">$hook</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'pre_system'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span>
<span style="color: #0000ff;">'function'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'preflight_check'</span><span style="color: #339933;">,</span>
<span style="color: #0000ff;">'filename'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'preflight_check_hook.php'</span><span style="color: #339933;">,</span>
<span style="color: #0000ff;">'filepath'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'hooks'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This will tell CodeIgniter to run this hook every time the system starts.  As you can infer from the above code, we&#8217;ll now have to create a file in the <em>application/hooks/</em> folder (if it doesn&#8217;t exist, create it) named <strong>preflight_check_hook.php</strong> and add a function to that file named <strong>preflight_check()</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Preflight Check checks all of the prerequistes before the first
 * pageview for each session.
 *
 * If a problem is found, the program halts execution.
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> preflight_check<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//all your checks go here</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now we&#8217;re ready to add checks so we can test the server environment.</p>
<a name="What+to+Check"></a><h2>What to Check</h2>
<p>Technically, you can check whatever you want here, but I tend to check the things that are likely to be different from one server environment to the next.  Some of the more important ones are:</p>
<ul>
<li>Whether the version of PHP or CodeIgniter is new enough to support your application.  You can check this by using the <em>phpversion()</em> function</li>
<li>Necessary PHP Extensions installed?  You can check this by using the <em>function_exists()</em> function.</li>
<li>PHP.INI variables set correctly?  You can check this by using the <em>ini_get()<strong> </strong></em>function.</li>
<li>Whether certain folders are really writable on the server or not</li>
<li>Whether files exist or not.</li>
</ul>
<p>Of course, you can check for most anything you want to in the preflight check, and even try to tweak the environment a little using <em>ini_set()</em>.  What you <span style="text-decoration: underline;">can&#8217;t</span> do is access most of the functionality in CodeIgniter, since this hook will run before most of your libraries are loaded.  There are a few useful CodeIgniter variables and functions that you will have access to, though:</p>
<ul>
<li><em>show_error()</em> &#8212; For printing out errors (non CodeIgniter users should use the <em>die()</em> function)</li>
<li><em>is_really_writable()</em> &#8212; For testing if a file is writable or not (non CodeIgniter users should use the <em>is_readable()</em> function)</li>
<li><em>$application_folder </em>and <em>$system_folder</em></li>
</ul>
<p>Rather than bore you with lengthy explanations of each type of check, it will be easier to simply show you an example of how I typically do it.  Below is an example preflight check hook that I ripped almost verbatim from one of my applications:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> preflight_check<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$application_folder</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$system_folder</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Ensure proper version of PHP</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">phpversion</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'5.1'</span><span style="color: #009900;">&#41;</span>
	  show_error<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;This application requires at least PHP 5.1 to run properly!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Ensure SQLITE extension is installed</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mysql_connect'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	  show_error<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;The sqlite PHP extension is required to run this application!  Refer to &lt;a href=&quot;</span>http<span style="color: #339933;">:</span><span style="color: #666666; font-style: italic;">//us.php.net/manual/en/book.sqlite.php&quot;&gt;the PHP documentation for this extension&lt;/a&gt; for more information.&quot;);</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Ensure GD2 is is installed</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;gd_info&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		show_error<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;The PHP GD2 image library is required to run this software.  Check with your server administrator or hosting provider, or &lt;a title=&quot;</span>Installation Instructions <span style="color: #b1b100;">for</span> GD2<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span>refer to the PHP documentation <span style="color: #b1b100;">for</span> installation instructions<span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;/</span>a<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;.&amp;</span>quot<span style="color: #339933;">;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 	<span style="color: #666666; font-style: italic;">//Check if the system cache directory is writable 	if ( ! is_really_writable($system_folder . &quot; href=&quot;http://us2.php.net/manual/en/intro.image.php&quot;&gt;&lt;/a&gt;&lt;a title=&quot;JSON extension installation instructions&quot; href=&quot;http://us3.php.net/manual/en/book.json.php&quot;&gt;manually install it&lt;/a&gt;.)&quot;);</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Check memory limit and attempt to set it to what this application needs</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>get_bytes<span style="color: #009900;">&#40;</span><span style="color: #990000;">ini_get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'php_value memory_limit'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">33554432</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">ini_set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'php_value_memory_limit'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'32m'</span><span style="color: #009900;">&#41;</span>
			show_error<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;The memory limit in your PHP.INI file must be set to at least 32 megabytes (32m).&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>You can copy this code into your <em>application/hooks/preflight_check_hook.php</em> and try it out.  Basically, it will halt execution (via the <em>show_error()</em> function) and show an error on the screen that alerts the user to something not being setup correctly if any one of these checks fails.</p>
<a name="What%26%238217%3Bs+the+Advantage+over+just+letting+the+program+fail+on+its+own%3F"></a><h2>What&#8217;s the Advantage over just letting the program fail on its own?</h2>
<p>Technically, nothing; your preflight checker will check things that would normally cause your application to fail at some point in the execution anyway.  This is simply a way for you to alert your admins/developers/users that they need to fix their environment right off the bat.  Plus it&#8217;s more graceful and clean than PHP error messages.</p>
<p>Practically, however, this may save a lot of headaches, especially if you distribute the application or expect people to download a copy onto their own desktops for development.  Oh, and if your users/developers/admins have PHP error reporting turned off on their system, then a carefully coded preflight checker will save them from getting a mysterious blank screen when the environment doesn&#8217;t match the requirements.</p>
<a name="Keeping+this+thing+from+running+for+every+page+view"></a><h2>Keeping this thing from running for every page view</h2>
<p>You probably won&#8217;t want this script to run every time a  page is loaded on your site, especially if the script includes file operations, lest your server take a performance hit.  Typically, you will want to run this preflight checker only once per session.  By adding a few lines of code to the top and bottom of this function, you can make it run only once per session (unless it fails).</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> preflight_check<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">//See if this has already been run during the current session</span>
	<span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'preflight_check_pass'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> <span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'preflight_check_pass'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'pass'</span><span style="color: #009900;">&#41;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$application_folder</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$system_folder</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Ensure proper version of PHP</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">phpversion</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'5.1'</span><span style="color: #009900;">&#41;</span>
	  show_error<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;This application requires at least PHP 5.1 to run properly!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// All of the</span>
	<span style="color: #666666; font-style: italic;">// rest of your checks</span>
	<span style="color: #666666; font-style: italic;">// go in here...</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//Woo hoo.. the check passed!</span>
	<span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'preflight_check_pass'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'pass'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>You&#8217;ll notice that this example uses PHP&#8217;s built-in session system rather than CodeIgniter&#8217;s session library.  This is because CodeIgniter&#8217;s will not have been loaded yet when this hook runs, and because we&#8217;re not storing any particularly sensitive information in this session, so we don&#8217;t have to take advantage of CI&#8217;s advanced session security features.</p>
<p>Well, that&#8217;s about it for now.  If you have any comments or see any issues with the examples in today&#8217;s post, feel free to share by leaving a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2009/06/codeigniter-preflight-checker/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Making PHP Applications Portable</title>
		<link>http://www.caseymclaughlin.com/2009/06/making-php-applications-portable/</link>
		<comments>http://www.caseymclaughlin.com/2009/06/making-php-applications-portable/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 19:27:27 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[portability]]></category>
		<category><![CDATA[portable]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=56</guid>
		<description><![CDATA[This post is the first in a two-part series explaining the virtues of portability when designing PHP applications, and provides a checklist of do's and don'ts (mostly don'ts) for ensuring that your application will run in any PHP server environment.]]></description>
			<content:encoded><![CDATA[<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.type=&amp;rft.format=text&amp;rft.title=Making PHP Applications Portable&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2009-06-23&amp;rft.identifier=http://www.caseymclaughlin.com/2009/06/making-php-applications-portable/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=Web Development"></span>
<p><img class="alignright size-full wp-image-62" title="portable_computer_guy" src="http://www.caseymclaughlin.com/wp-content/uploads/2009/06/portable_computer_guy.jpg" alt="portable_computer_guy" width="225" height="158" />&#8220;Portable&#8221; means that your application is able to run on any PHP webserver with minimal fuss.</p>
<p>Ensuring portability is an absolute must for programs that are packaged and distributed for public consumption, like WordPress or MediaWiki.  But, you should aim for portability in all of your applications.  The ideal is a one or two-step installation process and only two or three system requirements:  1. <em>Webserver (IIS/Apache/etc)</em>, 2. <em>PHP v5.X+</em>, 3. <em>MySQL 4+</em>.</p>
<p><span id="more-56"></span></p>
<a name="Why+Make+it+Portable%3F"></a><h2>Why Make it Portable?</h2>
<p>For one, it keeps things simple.  The concept of portability meshes well with the <a title="Keep It Simple, Stupid." href="http://en.wikipedia.org/wiki/KISS_principle">KISS</a> concept that I value so highly.</p>
<p>Secondly, it makes deploying your application to a new server simple if the need ever arises.</p>
<p>Thirdly, it enables you to easily distribute your package to the world if that is your intention.  I, for one, simply hate installing web applications on my server with long lists of prerequisites and a lengthy install process, especially if one of those steps is to install <em>another</em> set of libraries (e.g. from PEAR) before installing the application itself.</p>
<p>Finally, portability makes distributed development easier.  Many applications are developed on Windows but run on Linux.  Portable applications eliminate the headaches involved in trying to get the to two environments (development &amp; production) to match.</p>
<a name="How+to+Make+Your+Application+Portable"></a><h2>How to Make Your Application Portable</h2>
<p>A truly portable application will work out-of-the-box, and require minimal configuration.  It will also automatically check the environment for specific configuration or prerequisites that <em>do </em>happen to be required.  Below are five things to try and avoid, and one thing to try and do to ensure your application is portable:</p>
<a name="1.+Don%26%238217%3Bt+rely+on+exotic+PHP+extensions"></a><h3>1. Don&#8217;t rely on exotic PHP extensions</h3>
<p>I&#8217;m talking about extensions that are not bundled with PHP or found pre-installed on most hosting providers.  If you do require a specific PHP extension that is not bundled with PHP, you should check for the existence of the extension at the beginning of the program&#8217;s execution.</p>
<p>For example, many of my applications require JSON libraries, which some versions of PHP5 do not include, so I check for the existence of the <em>json_encode</em> function when the application first runs.</p>
<a name="2.+Don%26%238217%3Bt+rely+on+separate+installation+of+PEAR+Libraries"></a><h3>2. Don&#8217;t rely on separate installation of PEAR Libraries</h3>
<p>Don&#8217;t get me wrong; PEAR is great.  But, you shouldn&#8217;t predicate the successful execution of your application on your users installing external libraries.  Most PEAR libraries are dependent on other PEAR libraries, and require the user to figure out and install multiple packages.  Your application should not require this pre-setup, and it should run with all of the required libraries and classes included.</p>
<a name="3.+Don%26%238217%3Bt+rely+on+command-line+configuration"></a><h3>3. Don&#8217;t rely on command-line configuration</h3>
<p>If you want your application to be truly portable, you have to cater to the crowd who has only FTP access to their servers.  Yes, these folks are few-and-far-between, but coding with them in mind ensures that your application setup procedure is as simple as possible.  This means that your installation instructions should be completely void of anything that says <em>&#8220;login to the command line and run xyz command&#8221;</em>.</p>
<p>Definitely don&#8217;t rely on the user to have administrative privileges on the server.  This means to try to avoide the necessity for external software or packages (although this is unavoidable sometimes).</p>
<a name="4.+Don%26%238217%3Bt+rely+on+the+program+to+be+run+on+a+specific+operating+system"></a><h3>4. Don&#8217;t rely on the program to be run on a specific operating system</h3>
<p>This one is  a stretch for some people, but truly portable applications can run on Windows, Linux, or MAC servers without fuss.  I make all my applications portable enough to run on any OS  simply because we use SVN for development, which requires my developers to download fully working copies of the project to their desktops.  Since my developers use Windows &amp; Mac, and my servers run Linux, my applications have to be cross-platform compatible.</p>
<a name="5.+Don%26%238217%3Bt+rely+on+PHP.INI+customizations"></a><h3>5. Don&#8217;t rely on PHP.INI customizations</h3>
<p>A lot of PHP applications I have tried won&#8217;t work with magic quotes (or vice versa), or won&#8217;t work without the user increasing the amount of memory or upload file size  for PHP.   Before making these nice-to-have&#8217;s required, ask yourself if you can find a different way to solve the problem.</p>
<p>For situations where it is unavoidable to ensure that a specific directive is set, your application should automatically attempt to override the default PHP.INI customization via <em>ini_set() </em>and then inform the user in <span style="text-decoration: underline;">plain English</span> that the ini value needs to be changed.</p>
<a name="6.+Do+include+a+mechanism+in+the+application+to+test+for+required+prerequisites+at+the+very+start+of+execution+%28or+as+part+of+the+installation+process%29"></a><h3>6. <span style="text-decoration: underline;">Do</span> include a mechanism in the application to test for required prerequisites at the very start of execution (or as part of the installation process)</h3>
<p>Rather than have your application spit out a generic PHP error message when it comes across an environment setting that it doesn&#8217;t like, you should include a function that performs a &#8220;pre-flight checklist&#8221; at the beginning of runtime for each session, or at least the very first time your application is run.</p>
<p>Next week, I will show you how to do exactly this by creating a hook in <a title="CodeIgniter Homepage" href="http://codeigniter.com">CodeIgniter</a> that thoroughly tests the environment, and informs the user how to remedy issues.</p>
<a name="For+Further+Reading%2C+I+recommend%3A"></a><h6>For Further Reading, I recommend:</h6>
<ul>
<li><a title="&quot;Writing Portable PHP Code&quot; article" href="http://www.phpwact.org/php/writing_portable_php_code">Writing Portable PHP Code</a> from <a title="Web Application Toolkit" href="http://www.phpwact.org">PHPwact.org</a></li>
<li><a title="&quot;Making Your PHP Code Portable&quot; Article" href="http://www.mtdev.com/2002/09/make-your-php-code-portable">Making Your PHP Code Portable</a> from <a title="mtDev" href="http://mtdev.com">mtdev.com</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2009/06/making-php-applications-portable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

