<?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</title>
	<atom:link href="http://www.caseymclaughlin.com/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>Setup a local configuration file in Codeigniter</title>
		<link>http://www.caseymclaughlin.com/2011/04/setup-a-local-configuration-file-in-codeigniter/</link>
		<comments>http://www.caseymclaughlin.com/2011/04/setup-a-local-configuration-file-in-codeigniter/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 20:59:37 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[local config]]></category>
		<category><![CDATA[portability]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=316</guid>
		<description><![CDATA[In this article, I describe how to create a CodeIgniter local config file that overrides settings in the main config.php file in order to improve portability among different environments.]]></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=Setup a local configuration file in Codeigniter&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2011-04-29&amp;rft.identifier=http://www.caseymclaughlin.com/2011/04/setup-a-local-configuration-file-in-codeigniter/&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/2011/04/3019282806_ce005967b2.jpg"><img src="http://www.caseymclaughlin.com/wp-content/uploads/2011/04/3019282806_ce005967b2-150x150.jpg" alt="Even if you have twenty local environments on //one freaking computer//, this technique still works :)" title="Even if you have twenty local environments on //one freaking computer//, this technique still works :)" width="150" height="150" class="alignright size-thumbnail wp-image-326" /></a>After four years of development, I&#8217;m still a big <a title="CodeIgniter Homepage" href='http://codeigniter.com'>CodeIgniter</a> fan, although some <a title="FuelPHP Website" href="http://fuelphp.com/">other</a> <a title="Kohana Website" href="http://kohanaframework.org/">frameworks</a> are starting to look mighty interesting.  Despite the bugs in Version 2.0.2, however, CI is heading in the right direction.</p>
<p>One CI-related issue that has caused problems for my workplace in the past has been the ability to setup distributed development environments.  Everybody has a different local setup, and some of the configuration directives inside of CI&#8217;s <em>application/config</em> folder must change from machine to machine.</p>
<p>Of course, we can&#8217;t just tell Mercurial to ignore that folder during commits, because there are some configuration directives that <em>should</em> remain the same across all environments, such as <em>language, charset, enable_hooks, etc</em>.</p>
<p>So, how to make some configuration settings consistent across different computers, and how to make some local settings?<br />
<span id="more-316"></span></p>
<a name="Enter%3A+config.local.php."></a><h3>Enter: <em>config.local.php</em>.</h3>
<p>The solution is to create a local configuration file that overrides default <em>config.php</em> settings.  This way, local environments can set certain settings locally, and use the defaults in the <em>application/config</em> folder by default.  Here&#8217;s how to do it:</p>
<p><strong>Step One:</strong> Create a local configuration file, and add certain configuration settings that you want to override.  You can put it in your root folder, and name it <em>./config.local.php</em> For example:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">defined</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'BASEPATH'</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;">'No direct script access allowed'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* Local Configuration Options */</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;base_url&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;http://localhost/projects/my_project/&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;index_page&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;index.php&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;uri_protocol&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;AUTO&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;email_protocol&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;sendmail&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;mailpath&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;/usr/bin/sendmail&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;smtp_host&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;smtp_user&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;smtp_pass&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;smtp_port&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;25&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;smtp_timeout&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;5&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'log_threshold'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//..and whatever else you want to override..</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* EOF */</span></pre></td></tr></table></div>

<p><strong>Step Two:</strong> Set your version control system to ignore this file.  If you&#8217;re using Mercurial, simply add a line to the <em>.hgignore</em> file:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;">^config\.local\.php$</pre></td></tr></table></div>

<p><strong>Step Three:</strong> Subclass the <em>core/Config.php</em> library to read the local configuration file after reading the default one every time.  To do this, create the file <em>application/core/MY_Config.php</em> in your application folder, and add the following code inside that file:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">defined</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'BASEPATH'</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;">'No direct script access allowed'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> MY_Config <span style="color: #000000; font-weight: bold;">extends</span> CI_Config
<span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * Load a config file - Overrides built-in CodeIgniter config file loader
	 * 
	 * @param string $file
	 * @param boolean $use_sections
	 * @param boolean $fail_gracefully 
	 */</span>
	<span style="color: #000000; font-weight: bold;">function</span> load<span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$use_sections</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fail_gracefully</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		parent<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">,</span> <span style="color: #000088;">$use_sections</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fail_gracefully</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Local settings override permanent settings always.</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_readable</span><span style="color: #009900;">&#40;</span>FCPATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'system/config.local.php'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			parent<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'system/config.local.php'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$use_sections</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fail_gracefully</span><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;">/* EOF: MY_Config */</span></pre></td></tr></table></div>

<a name="Using+local+settings+for+database+Configuration"></a><h3>Using local settings for database Configuration</h3>
<p>Another file that is likely to be completely different from one environment to the next is the <em>application/config/database.php</em> file.  Since CodeIgniter seems to read the database settings a bit differently than normal settings, we have to go through one extra step to override those.  It&#8217;s a bit messier than I&#8217;d like, but gets the job done:</p>
<p><strong>Step One</strong>: Add a line to your <em>config.local.php </em>for each database setting you want to override, but put the database settings in their own sub-array:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//...inside the local config file...</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;hostname&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;localhost&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;username&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;localuser&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;password&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;database&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;oeg_dev&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db_debug&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;TRUE&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;dbdriver&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;mysql&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p><strong>Step Two</strong>: Add the following code to the end of the <em>application/config/database.php</em> file to read those settings after reading the default settings:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//If there is a local config file, overwrite the settings with that..</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_readable</span><span style="color: #009900;">&#40;</span>FCPATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'config.local.php'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">include_once</span><span style="color: #009900;">&#40;</span>FCPATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'config.local.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$db</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$val</span><span style="color: #009900;">&#41;</span>
		<span style="color: #000088;">$db</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'db'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$val</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>There you have it!  From now on, you can your local configuration file to override any configuration setting in CodeIgniter.  This makes sharing code a breeze.  You developers can set their own <em>base_path</em>, <em>database</em>, <em>index_file</em> and other settings that are likely to change from one environment to the next without modifying the main configuration files.</p>
<p><strong>PS.</strong> Happy Friday!</p>
<p><strong>PPS.</strong> Have a better method?  I&#8217;d love to hear about it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2011/04/setup-a-local-configuration-file-in-codeigniter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Command-Line Fridays</title>
		<link>http://www.caseymclaughlin.com/2011/04/command-line-fridays-4/</link>
		<comments>http://www.caseymclaughlin.com/2011/04/command-line-fridays-4/#comments</comments>
		<pubDate>Fri, 01 Apr 2011 18:59:36 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[cli tools]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[command line fridays]]></category>
		<category><![CDATA[fun]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/2011/04/command-line-fridays-4/</guid>
		<description><![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=Command-Line Fridays&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2011-04-01&amp;rft.identifier=http://www.caseymclaughlin.com/2011/04/command-line-fridays-4/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=General"></span>
So where have I been these days? In between my six jobs, I&#8217;ve decided that instead of updating this blog, I&#8217;d drink some beer. However, we&#8217;ve run out of beer, so here I am. Which is good for you, because I have a great big awesome announcement: Command Line Fridays start today! GUIs are great [...]]]></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=Command-Line Fridays&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2011-04-01&amp;rft.identifier=http://www.caseymclaughlin.com/2011/04/command-line-fridays-4/&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/2011/04/command-line.png"><img class="alignright size-thumbnail wp-image-310" title="command-line" src="http://www.caseymclaughlin.com/wp-content/uploads/2011/04/command-line-150x150.png" alt="The CLI - For Winners Only!" width="150" height="150" /></a>So where have I been these days? In between my six jobs, I&#8217;ve decided that instead of updating this blog, I&#8217;d drink some beer.  However, we&#8217;ve run out of beer, so here I am.  Which is good for you, because I have a great big awesome announcement:</p>
<p>Command Line Fridays start today!</p>
<p>GUIs are great and all, and they certainly have their place, but for those of us nerds who love our keyboards (I&#8217;m the <a title="Comic" href="http://goo.gl/FeN1p">guy on the right</a>), it doesn&#8217;t get any better than the old CLI.<span id="more-307"></span></p>
<p>So, here are the rules of Command Line Fridays:</p>
<ul>
<li>You must use the CLI to perform all of your core duties all day long</li>
<li>You may not open a GUI at any point during the day.  If you open a GUI, <strong>YOU LOSE!</strong></li>
<li>You can use any CLI you like, but seriously, Windows CLI?  Come on&#8230;</li>
</ul>
<p>The cool thing is, even though it is 2011, you can still not only be ridiculously productive on the CLI, you can even slack off.  You can Tweet and Facebook from the CLI, write documents, listen to music, code, run applications, view web sites, and generally get stuff done.</p>
<p>Here are a list of programs to get you started:</p>
<ul>
<li><a title="Wordpress CLI" href="http://search.cpan.org/~leocharre/WordPress-CLI-1.03/">WordPress CLI</a> &#8211; Where do you think this blog post was written from?  Post media and content to WordPress, and view WordPress blogs.</li>
<li><a title="Good ol VIM" href="http://www.vim.org/">VIM</a> &#8211; Code in any programming language, or just write stuff.  As powerful as any GUI IDE, and all keyboard based!</li>
<li><a title="Twidge Twitter Client!" href="https://github.com/jgoerzen/twidge/wiki">Twidge</a> &#8211; Post to, and read Twitter</li>
<li><a title="PianoBar for Pandora!" href="https://github.com/PromyLOPh/pianobar">PianoBar</a> &#8211; Listen to Pandora from the Command-Line (!)</li>
<li><a title="Linx Web Browser" href="http://en.wikipedia.org/wiki/Lynx_(web_browser)">Lynx</a> &#8211; An up-to-date, text-based web browser for the CLI</li>
<li><a title="FBCMD Facebook Client" href="http://fbcmd.dtompkins.com/">FBCMD</a> &#8211; A command-line Facebook client.  Read and Post</li>
<li><a title="CIM IM Client" href="http://www.centerim.org/index.php/Main_Page">CenterIM</a> &#8211; A full-featured IM client for Google, Yahoo, etc.</li>
<li><a title="Mutt CLI Email Client" href="http://www.mutt.org/">Mutt</a> &#8211; An email client that works with IMAP, POP3, and <a title="Andrews Corner Tutorial on Mutt &amp; Gmail" href="http://www.andrews-corner.org/mutt.html">can be connected to Gmail</a></li>
</ul>
<p>Look at all that cool stuff you can do!  With all of that (and trust me&#8211;the list goes on..), why would anybody want to dink around with an inefficient mouse&#8211;the most inferior of all input devices (well.. maybe the trackball is worse).</p>
<p>So, go forth, CLI-lovers.  I&#8217;ll see you in BASH.  Happy Friday, and if I forgot to mention it three months ago, happy 2011.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2011/04/command-line-fridays-4/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>My Mercurial Workflow</title>
		<link>http://www.caseymclaughlin.com/2010/11/my-mercurial-workflow/</link>
		<comments>http://www.caseymclaughlin.com/2010/11/my-mercurial-workflow/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 17:39:56 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[IT Management]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[diagrams]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[vcs]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=282</guid>
		<description><![CDATA[This post contains a few diagrams I worked up for colleagues at work to describe the Mercurial workflow.]]></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=My Mercurial Workflow&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-11-22&amp;rft.identifier=http://www.caseymclaughlin.com/2010/11/my-mercurial-workflow/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=IT Management&amp;rft.subject=Web Development"></span>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/programming_principles.jpg"><img class="alignright size-thumbnail wp-image-294" title="Programming Principles" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/programming_principles-150x150.jpg" alt="Where does VCS fit in here?" width="150" height="150" /></a>About a year ago, I wrote an article on this website about Version Control.  In <a title="VCS .. The early days :)" href="http://www.caseymclaughlin.com/2009/12/make-codeigniter-svn-friendly/">that article</a>, I touted the glory of Subversion, and mentioned:</p>
<blockquote><p>&#8220;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.&#8221;</p></blockquote>
<p>Well, I&#8217;ve since found my compelling reasons to switch.  SVN lost some of our files, and it was a pain to do all sorts of stuff (get setup, keep clean, branch, merge, etc).  I won&#8217;t get into; there are <a title="Google will show you." href="http://www.google.com/search?sourceid=chrome&amp;ie=UTF-8&amp;q=subversion+sucks">enough rants about Subversion</a> on the &#8216;net already.  We use Mercurial now, and boy has our workflow improved.</p>
<p>Mercurial is my new favorite child, because it&#8217;s easy to setup, easy to use, easy to branch and merge, and easy to teach to my students.  Oh, and it just works.  <a title="I got rather excited in September." href="http://twitter.com/#!/caseyamcl/status/23944288332">Sometimes</a> I think it runs off magic.<span id="more-282"></span></p>
<p>In order to help my colleagues make the transition from SVN to Hg, I came up with a few diagrams to explain the workflow.  I thought I&#8217;d share them here.</p>
<a name="Mercurial+Recipe+for+Success"></a><h2>Mercurial Recipe for Success</h2>
<a name="You+will+Need%3A"></a><h5>You will Need:</h5>
<ol>
<li>Mercurial.  <a title="Hg Website." href="http://mercurial.selenic.com/">Grab and install it from the official site</a>.</li>
<li>Your files.  You know, all of those <em>css, html, </em>and<em> php</em> files that you&#8217;ve been working so hard on.</li>
<li>A repository server.  If you don&#8217;t have one, go get a free account at <a title="Bitbucket Mercurial Hosting (Free)" href="http://www.bitbucket.org">Bitbucket</a>.</li>
<li>A web server.  Install Mercurial here too.</li>
</ol>
<a name="The+Workflow%3A"></a><h5>The Workflow:</h5>
<div id="attachment_286" class="wp-caption aligncenter" style="width: 608px"><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/Hg-Setup.png"><img class="size-full wp-image-286 " title="Hg Setup" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/Hg-Setup.png" alt="Diagram showing steps to setup a Mercurial Repository" width="598" height="338" /></a><p class="wp-caption-text">Setting up a Mercurial Repository</p></div>
<div id="attachment_287" class="wp-caption aligncenter" style="width: 608px"><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/Hg-Workflow.png"><img class="size-full wp-image-287 " title="Hg Workflow" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/Hg-Workflow.png" alt="Diagram showing day-to-day Hg Workflow" width="598" height="305" /></a><p class="wp-caption-text">Day-to-Day Developer Workflow</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/11/my-mercurial-workflow/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How To Use SSH Tunnels with HeidiSQL and Plink</title>
		<link>http://www.caseymclaughlin.com/2010/11/how-to-use-ssh-tunnels-with-heidisql-and-plink/</link>
		<comments>http://www.caseymclaughlin.com/2010/11/how-to-use-ssh-tunnels-with-heidisql-and-plink/#comments</comments>
		<pubDate>Fri, 05 Nov 2010 18:27:13 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[heidisql]]></category>
		<category><![CDATA[IT Management]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[plink]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[ssh tunnel]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=259</guid>
		<description><![CDATA[In this post, I was poetically about HeidiSQL for a few sentences, and then I explain how to use HeidiSQL and Plink to successfully connect to MySQL servers through SSH Tunneling.]]></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=How To Use SSH Tunnels with HeidiSQL and Plink&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-11-05&amp;rft.identifier=http://www.caseymclaughlin.com/2010/11/how-to-use-ssh-tunnels-with-heidisql-and-plink/&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/11/ImageWorks.jpg"><img class="alignright size-thumbnail wp-image-262" title="Tunnel!" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/ImageWorks-150x150.jpg" alt="It's a magic SSH tunnel!" width="150" height="150" /></a>Do you love <a title="HeidiSQL" href="http://www.heidisql.com">HeidiSQL</a> as much as I do?  It&#8217;s really the best MySQL front-end I&#8217;ve found so far for Windows.  Sure, <a title="MySQL Workbench" href="http://wb.mysql.com/">MySQL Workbench</a> has all kinds of super-fancy features and GUI tools and what-not.  But, in Workbench, I find that it takes sixteen mouse clicks to perform the same task that you can do in five with HeidiSQL.</p>
<p>I use HeidiSQL for nearly everything, and only have had one major beef with it.  I could never get SSH Tunnels to work with it until today <em>I figured it out!</em> I&#8217;m super-stoked.  If you&#8217;re having problems with Heidi and SSH too, I&#8217;ll provide a step-by-step below (keep reading).</p>
<p>If you want to skip the background junk, and go right to the procedure, <a title="Go on down to the content yer lookin fer." href="http://www.caseymclaughlin.com/2010/11/how-to-use-ssh-tunnels-with-heidisql-and-plink#Setting+it+Up">be my guest</a>!</p>
<a name="First%3A+Why+SSH+Tunnels%3F"></a><h3><span id="more-259"></span>First: Why SSH Tunnels?</h3>
<p>Okay, if you&#8217;re reading this article, I assume you are at-least familiar with MySQL and HeidiSQL.  Chances are, you connect to your database server via the default port 3306.  You open up HeidiSQL, enter your DB Username, password, and host, and away you go.</p>
<p>The problem with this approach is that the MySQL protocol that you are using to transfer your data around is inherently insecure.  Folks sniffing network traffic can intercept your data as it travels over the network.  So, if you care about your data or your database not being hacked, it&#8217;s a good idea to encrypt the traffic between your client (HeidiSQL) and your server (MySQL Server).</p>
<div id="attachment_260" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/insecure_mysql.png"><img class="size-medium wp-image-260" title="Insecure MysQL" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/insecure_mysql-300x95.png" alt="Not a Good Way To Do Things" width="300" height="95" /></a><p class="wp-caption-text">Insecure MySQL Traffic Flows Across the &#39;Net as Plaintext</p></div>
<p>SSH, on the other hand, is a secure protocol.  All traffic between the client and the server is encrypted so that nefarious network sniffer folks can&#8217;t decrypt the traffic (easily).</p>
<p>What you want to do is to convert the insecure MySQL traffic to secure SSH traffic on your computer before it hits the Internet.  On the server-side, you want to decode the SSH traffic and pass it along the MySQL server.   Something like this:</p>
<div id="attachment_261" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/secure_ssh_traffic.png"><img class="size-medium wp-image-261" title="Secure SSH Tunnel" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/11/secure_ssh_traffic-300x176.png" alt="This is much better" width="300" height="176" /></a><p class="wp-caption-text">SSH Tunnel.  All data travels across the &#39;net as SSH</p></div>
<a name="Setting+it+Up"></a><h3>Setting it Up</h3>
<p>First, make sure you know what your SSH username and password are on the server where your MySQL database lives.  Then, follow along:</p>
<ol>
<li><a title="Make sure you choose &quot;Plink&quot;" href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">Download Plink.exe</a>.  Plink is a nifty little SSH tool for Windows that allows you easily setup a SSH tunnel.</li>
<li>Place the downloaded file anywhere on your hard-drive you wish.  It&#8217;s probably a good idea to put it somewhere inside your home directory.</li>
<li>Now (this is the step that kept tripping  me up), before HeidiSQL can use Plink to connect to your server, you must download the server&#8217;s public key to your computer.</li>
<li>So, fire up your command-line, and browse to wherever you put the <em>plink.exe</em> file.</li>
<li>Type: <strong>plink.exe -L 3307:localhost:3306 [USERNAME]@[YOURSERVER.COM]</strong></li>
<li>If it worked, you&#8217;ll get a big long message that ends with <em>&#8220;Store key in Cache? (y/n)&#8221;</em></li>
<li>Say &#8220;yes&#8221;, of course.  Where does it put this key?  That was a mystery to me too!  It turns out, when you say yes, Plink will put the key into your Windows Registry (at HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys).</li>
<li>Type your password, and then type &#8220;exit&#8221; to finish up this step.</li>
<li>Okay, now that you&#8217;ve downloaded the key, you&#8217;re ready to use SSH Tunneling in HeidiSQL!</li>
<li>Fire up HeidiSQL</li>
<li>Create a new connection, and choose &#8220;SSH Tunnel&#8221; from the &#8220;Network Type&#8221; dropdown.</li>
<li>Inside the &#8220;Settings&#8221; tab, use &#8220;127.0.0.1&#8243; for the hostname.  Then, enter your normal database username and password.  Yep, 127.0.0.1 is correct.  You enter the address as if you were logged-in to the server via SSH.</li>
<li>Next, flip to the &#8220;SSH Tunnel&#8221; tab.  Tell HeidiSQL where the <em>plink.exe </em>file is on your hard-drive, then put the <strong>actual </strong>IP address or DNS name for your database server.  Use 22 (SSH) for the port.</li>
<li>Enter your SSH username and password, and then choose &#8220;3307&#8243; (or some other unused port) on your computer for the &#8220;Local Port&#8221;.</li>
<li>Let &#8216;er rip!</li>
</ol>
<p>If all is well, and the powers-that-be are smiling down on you, you&#8217;ll be able to login to click &#8220;Open&#8221; and everything will work.  Congrats!  Now all your database traffic is travelling through the tubes securely.</p>
<p>If it doesn&#8217;t work, it&#8217;s time to check your steps or go bother somebody in the <a title="Be Nice.  They build this stuff for free!" href="http://www.heidisql.com/forum.php">HeidiSQL forums</a>.</p>
<p>Happy Friday!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/11/how-to-use-ssh-tunnels-with-heidisql-and-plink/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<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>Gone is Gone: The Case Against &#8220;Delete&#8221;</title>
		<link>http://www.caseymclaughlin.com/2010/03/gone-is-gone-the-case-against-delete/</link>
		<comments>http://www.caseymclaughlin.com/2010/03/gone-is-gone-the-case-against-delete/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 21:35:36 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=195</guid>
		<description><![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=Gone is Gone: The Case Against &#8220;Delete&#8221;&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-03-08&amp;rft.identifier=http://www.caseymclaughlin.com/2010/03/gone-is-gone-the-case-against-delete/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=Web Development"></span>
I love, love, love getting rid of crap.  Maybe that&#8217;s why I like to read Unclutterer, or think that the 100 Things Challenge is such a great idea.  In real-life, I&#8217;m a minimalist, but when it comes to programming web apps, I&#8217;ve become a digital pack-rat. I don&#8217;t care if my database grows into a giant data-monster, [...]]]></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=Gone is Gone: The Case Against &#8220;Delete&#8221;&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-03-08&amp;rft.identifier=http://www.caseymclaughlin.com/2010/03/gone-is-gone-the-case-against-delete/&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/03/a_bomb2.jpg"><img class="size-thumbnail wp-image-201 alignright" title="The Effects of Deleting Data" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/03/a_bomb2-150x150.jpg" alt="The Effects of Deleting Data" width="150" height="150" /></a>I love, love, love getting rid of crap.  Maybe that&#8217;s why I like to read <a title="Unclutterer Blog - People who think up my ally" href="http://unclutterer.com/">Unclutterer</a>, or think that the <a title="100 Things Challenge - Great Concept!" href="http://www.guynameddave.com/100-thing-challenge.html">100 Things Challenge</a> is such a great idea.  In real-life, I&#8217;m a minimalist, but when it comes to programming web apps, I&#8217;ve become a digital pack-rat.</p>
<p>I don&#8217;t care if my database grows into a giant data-monster, ready to ravage my server&#8217;s hard disk and slow queries down to a crawl; I&#8217;ll deal with it.  The key here is to not allow any important history of data to get lost.</p>
<p><img title="More..." src="http://www.caseymclaughlin.com/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /><span id="more-195"></span></p>
<a name="Why+Deleting+is+Bad"></a><h2>Why Deleting is Bad</h2>
<p>Here&#8217;s an example, to get us started:</p>
<p>Let&#8217;s say you have a simple online store, and you&#8217;re selling <a title="The Definition of Importance" href="http://stupid.com">important consumer items</a> to important people.  You have a database that keeps track of your customers, your products, and your transactions.  It may look something like this:</p>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/03/simple-db.png"><img title="Database Example" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/03/simple-db.png" alt="Database Example" width="625" height="136" /></a>So, you&#8217;ve been in business for a while, and you have a bunch of customers in the system, quite a few products, and a lengthy transaction history.  Recently, you&#8217;ve decided to stop selling your <a title="An Important Asset for every Household" href="http://www.stupid.com/fun/D-MOLD.html">Jell-O Brain Mold</a> and you&#8217;re ready to remove it from your online store.  Common sense says that you would go to your database, find the record referring to your product, and delete it.</p>
<p>But wait!  If you do this, then the entire history of transactions linked to those products become orphaned (the<em>products_id</em> field will point to a non-existent record).  So, if you want to go back in at a future date to see the history of how many of those items that you sold, you will be in trouble.  You haven&#8217;t just deleted the item from your website per se, you&#8217;ve actually deleted the record of the item ever existing in the first place.</p>
<p>And, you don&#8217;t want to do that.</p>
<a name="Flag+It%21"></a><h2>Flag It!</h2>
<p>The useful alternative would be to add a flag to the data, so that instead of deleting the record, you could mark it as inactive.  This way, it wouldn&#8217;t appear on your website, but it would still exist in the database for future reference.</p>
<p>Your tables will now look something like:</p>
<p><a href="http://www.caseymclaughlin.com/wp-content/uploads/2010/03/simple-db-2.png"><img title="DB with Flags" src="http://www.caseymclaughlin.com/wp-content/uploads/2010/03/simple-db-2.png" alt="DB with Flags" width="625" height="151" /></a>Now you can tell your application to only show the products with `active` = &#8220;TRUE&#8221; on your website, but refer to products with `active` = &#8220;FALSE&#8221; when viewing older transaction histories.</p>
<p>This works pretty well, and if you program your User Interface correctly, your website users should never actually be deleting records; instead they should be marking them inactive so they &#8220;go away&#8221; but never truly die.</p>
<a name="Audit+History"></a><h2>Audit History</h2>
<p>Okay, now it gets a bit more complex.  In some cases, you don&#8217;t just want to mark a record &#8220;active&#8221; or &#8220;inactive&#8221; (that is, give it the ability to have two states), you also want to keep a complete revision history of that record, including what change was made, who made it, and when.  This way you can see what a record looked like at a particular moment in time.</p>
<p>This is not a new concept.  Think about your bank account.  It&#8217;s pretty much a bunch of numbers stored in a database somewhere.  Do you think that your checking account balance is simply a single field in a single record stored in a database?  Heck no!  Every single debit and credit is stored as a separate transaction, showing a complete history of changes to the account.</p>
<p>There are many ways to accomplish this, really, and for me to put up a tutorial, would be to <a title="Stack Overflow Thread on the Subject" href="http://stackoverflow.com/questions/323065/how-to-version-control-a-record-in-a-database">reinvent </a><a title="Arnold's (complex) solution" href="http://www.adaniels.nl/articles/versioning-mysql-data/">the</a> <a title="Another Tutorial for MS SQL" href="http://www.codeproject.com/KB/architecture/LisRecordVersioning.aspx">wheel</a>.  The key is to think about which data you want to have complete histories on, and which data is not expendable.  Design your application around these constraints.</p>
<a name="Sometimes+you+Just+Have+to+Kill+It"></a><h2>Sometimes you Just Have to Kill It</h2>
<p>I wrote an application that contains patient records.  When an administrator clicks &#8220;Delete&#8221;, the patient doesn&#8217;t really go away; all of the information remains in the database.  Sometimes, however, we <strong>must </strong>delete the record permanently. Usually this is because a patient opts out of the program and requests to be removed from the study.  I use a special word for this kind of delete: <strong>Purge</strong>.</p>
<p>But, before the record is purged, the user has to click a checkbox, and go through two <strong>&#8220;Are You Sure?&#8221;</strong> screens informing him or her that not only will the patient record be deleted, but also the complete history of that record, and all data associated with it.  I try to have the application show the data in question on the screen the user has to click yes to.</p>
<p>&#8230;well, that&#8217;s enough for now.  Hope you&#8217;re thinking about data consistency, so you too can become a digital pack rat.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/03/gone-is-gone-the-case-against-delete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backups and Disaster Recovery Kit</title>
		<link>http://www.caseymclaughlin.com/2010/01/backups-and-disaster-recovery-kit/</link>
		<comments>http://www.caseymclaughlin.com/2010/01/backups-and-disaster-recovery-kit/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 16:21:00 +0000</pubDate>
		<dc:creator>McLaughlin Casey</dc:creator>
				<category><![CDATA[IT Management]]></category>
		<category><![CDATA[backups]]></category>
		<category><![CDATA[basics]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.caseymclaughlin.com/?p=186</guid>
		<description><![CDATA[In this post, I chastise you, the reader, for presumably not backing up your department's data, and share how to create a portable DR kit.]]></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=Backups and Disaster Recovery Kit&amp;rft.source=Casey A. McLaughlin&amp;rft.date=2010-01-15&amp;rft.identifier=http://www.caseymclaughlin.com/2010/01/backups-and-disaster-recovery-kit/&amp;rft.language=English&amp;rft.aulast=McLaughlin&amp;rft.aufirst=Casey&amp;rft.subject=IT Management"></span>
<p><a href="../wp-content/uploads/2010/01/bear-survival-kit.jpg"><img class="alignright" title="bear-survival-kit" src="../wp-content/uploads/2010/01/bear-survival-kit-150x150.jpg" alt="Be Prepared!" width="150" height="150" /></a>It&#8217;s the perfect time to think about it.  With <a title="..and the subsequent media frenzy" href="http://en.wikipedia.org/wiki/2010_Haiti_earthquake">disaster</a> on everybody&#8217;s mind, and this being the season of resolutions, it&#8217;s time to think about your disaster recovery strategy.</p>
<p>Recently, a major department right here at FSU <a title="News article about the loss" href="http://cci.fsu.edu/news/?p=6580">suffered catastrophic loss</a> to their servers, with scant means of quick recovery.  Their site was down literally for weeks as staff from all over the University scrambled to assist them in recreating the critical pieces.  They lost of <em>a lot</em> of time and money.</p>
<p>I&#8217;m absolutely sure they&#8217;ll be super-prepared next time, but <span style="text-decoration: underline;"><em>you</em></span> don&#8217;t have to wait until something tragic happens to be prepared!</p>
<a name="Disaster+Recovery+Enterprise+Planning+%3D+Big+Words+%28Scary%21%29"></a><h3><span id="more-186"></span>Disaster Recovery Enterprise Planning = Big Words (Scary!)</h3>
<p>When I was an IT Manager n00b, I thought that planning for disasters was intimidating and complicated.  I thought it took a team of folks working around the clock, military-style, to prepare for incidents.  I was encouraged to believe this by colleagues constantly talking in <a title="Yeah... stuff like this" href="http://spedr.com/5rduk">business-speak</a>, conference sessions talking about <a title="Just like this." href="http://spedr.com/2v7ul">things like &#8220;DR evaluation metrics&#8221;</a>, and by <a title="Big Ugly Book" href="http://spedr.com/1frzy">big</a> <a title="What's the picture on the front of the book supposed to indicate?" href="http://spedr.com/3y867">ugly</a> <a title="More books" href="http://spedr.com/3wig0">books</a> that take days to even read through.</p>
<p>In the meantime, while I was being intimidated by all this &#8220;enterprise&#8221; stuff, we went without reliable backups.  We would have been <em>Scre-ewed</em> if something happened.</p>
<a name="1.+Embracing+Common+Sense"></a><h3>1. Embracing Common Sense</h3>
<p>Okay, just ignore all that business-speak.  Let&#8217;s start with the basics:  If you&#8217;re not backing up your data, put down the <a title="Big Ugly Book" href="http://spedr.com/1frzy">big</a> <a title="What's the picture on the front of the book supposed to indicate?" href="http://spedr.com/3y867">ugly</a> <a title="More books" href="http://spedr.com/3wig0">DR books</a> <em>right now</em> and go setup a backup.</p>
<p>No, seriously, do it <span style="text-decoration: underline;">right now</span>.</p>
<p>This does not have to be complicated.  Go find an external hard drive, then find out where your data is on your computers or servers.  Plug the hard-drive into the back of the computers and copy the folders with your data.  Do this every day, and you have a basic disaster recovery strategy!</p>
<blockquote><p><em>Pro Tip: </em>If you&#8217;re using Windows, I&#8217;m a big fan of using <a title="Seriously awesome freeware." href="http://www.codesector.com/teracopy.php">Teracopy</a> when I have to copy lots of data at a time.</p></blockquote>
<p>You get bonus if you copy the data to two hard-drives and take one off-site every day.  Now your data is in two geographic locations on three devices.</p>
<p>See? Easy.  Now that you&#8217;re off and running, you can make your life even easier by automating your backups.  If you&#8217;re not excited about doing a bunch of geeky tech stuff to get your automated backups working, go convince your boss to spend a few bucks a month on <a title="Mozy Pro Goodness" href="http://mozy.com/pro">cheap</a>, <a title="I Drive is good, too" href="http://www.idrive.com/">easy-to-setup</a> <a title="SOS Backup Services" href="http://www.sosonlinebackup.com/">online backup services</a>.  If he doesn&#8217;t want to spend the money, you can scare him with <a title="Coding Horror: Backup Awareness Day" href="http://spedr.com/5nizg">many</a> <a title="Company Fail" href="http://spedr.com/4jg32">horrifying</a> <a title="Marketing site, but still true" href="http://spedr.com/4niov">stories</a> of data loss on the Internet.</p>
<a name="2.+Being+Prepared"></a><h3>2. Being Prepared</h3>
<p>Next Step: Just sit down in a quiet place for a few minutes and think about the things that could go wrong:</p>
<ul>
<li>&#8220;My server could suffer a catastrophic hardware failure&#8221;</li>
<li>&#8220;My backup data could be corrupt&#8221;</li>
<li>&#8220;The building could burn down&#8221;</li>
<li>&#8220;We could get robbed&#8221;</li>
<li>&#8220;An employee could go apeshit and format the C: drive of the server&#8221;</li>
<li><em>etc..</em></li>
</ul>
<p>Now consider which three or four of those scenarios are most likely to happen in your department. You&#8217;ve just considered your risks.  Now, for each one of those scenarios, think about (a) what you can easily do to guard against them and (b) what you would have to do to recover from them:</p>
<ul>
<li>Buy a second, backup server (or set an old computer aside to act as server temporarily in case of disaster).</li>
<li>Keep two backup copies instead of one and periodically test opening files on the backup.</li>
<li>Take backups offsite so that the data doesn&#8217;t burn down with the rest of the building.</li>
<li>Lock the servers in a room without windows.</li>
<li>Keep backups (already done), and make sure employees don&#8217;t have too much access to the server.</li>
<li><em>etc..</em></li>
</ul>
<p>If you write all of this stuff down somewhere and tell your boss about it, you have a basic DR plan!  Go have a beer.</p>
<a name="3.+Building+Your+Kit"></a><h3>3. Building Your Kit</h3>
<p>Now that you are creating backups and thinking about our risks/responses, it&#8217;s time to build your <strong>Disaster Recovery Kit!</strong> Put this kit somewhere out of harm&#8217;s way, and have it handy in case you need it.  Here&#8217;s mine:</p>
<ol>
<li><strong>A camcorder bag</strong> &#8212; I like this, because it&#8217;s easy to carry and has a lot of compartments for all the stuff below:</li>
<li><strong>Operating System Boot discs </strong>&#8211; In my case, Ubuntu Server 8.04</li>
<li><strong>GParted Boot disc</strong> &#8212; For formatting and partitioning systems on-the-fly.</li>
<li><strong>Cables </strong>&#8211; Standard power cable and USB cable.</li>
<li><strong>Backup hard drives</strong> &#8212; Two.  They are my offsite copies of all our data.  I rotate them and keep them encrypted.</li>
<li><strong>Flash light </strong>&#8211; Small and compact, for poking around inside computers or navigating server rooms in the dark</li>
<li><strong>Thumb drive</strong> &#8212; Includes a backup of my server setup procedures/changelogs, systems passwords (in KeePass), and a bunch of portable apps.  Updated weekly.</li>
<li><strong>Printed copy of contact information for key stakeholders</strong> &#8212; My IT colleagues, clients, and my boss, so I can keep them updated.</li>
<li> <strong>Geek tool kit</strong> &#8211;  <a title="Belkin Basic Toolkit" href="http://spedr.com/3mv8z">Something like this</a>.  Includes screwdrivers, etc.</li>
<li><strong>External SATA Hard Disk Reader </strong>&#8211; Something<a title="StarTech USB SATA adapter" href="http://spedr.com/46suc"> small and compact</a>.  In case I need to rip a hard drive from a computer and get the data off quickly.</li>
<li><strong>A big sheet of paper that says <span style="color: #800000;">&#8220;<em>Don&#8217;t Panic</em>&#8220;</span></strong></li>
<li><strong>Music CD</strong> with high-energy power music on it.</li>
<li><strong>Energy supplement</strong> &#8212; Or a flask of whiskey, depending on how you roll.</li>
<li><strong>&#8220;Getting started&#8221; guide </strong>&#8211; A piece of paper, right on top, that explains briefly how to use the kit.</li>
<li><strong>Checklist</strong> &#8212; With all of these items on it, and with weekly DR Kit maintenance procedures.</li>
</ol>
<p>There, now I can sleep at night much better.  What&#8217;s in your DR Toolkit?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caseymclaughlin.com/2010/01/backups-and-disaster-recovery-kit/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>
	</channel>
</rss>

