<?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>Made of Everything You&#039;re Not</title>
	<atom:link href="http://blog.ericlamb.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ericlamb.net</link>
	<description>Thoughts on programming, people and life</description>
	<lastBuildDate>Mon, 13 Feb 2012 18:55:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Freelancing and the Hourly Rate</title>
		<link>http://blog.ericlamb.net/2012/02/freelancing-and-the-hourly-rate/</link>
		<comments>http://blog.ericlamb.net/2012/02/freelancing-and-the-hourly-rate/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 18:55:05 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[billing]]></category>
		<category><![CDATA[freelancing]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3861</guid>
		<description><![CDATA[When I, ahem, &#8220;left&#8221; StreetWise a couple years ago and started freelancing full time one of the first things I did was change up how I bill from, the traditional, project based scale into an hourly rate. I did this for a variety of reasons, mostly having to do with a lot of issues I [...]]]></description>
			<content:encoded><![CDATA[<p>When I, ahem, &#8220;left&#8221; <a href="http://blog.ericlamb.net/2009/07/goodbye-streetwise-it-was-fun/" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2009%2F07%2Fgoodbye-streetwise-it-was-fun%2F','StreetWise')">StreetWise</a> a couple years ago and started freelancing full time one of the first things I did was change up how I bill from, the traditional, project based scale into an hourly rate. I did this for a variety of reasons, mostly having to do with a lot of issues I see with the project pricing model. It certainly wasn&#8217;t an easy thing to do, but after a couple years of this I have to say it&#8217;s been very good to me and something I think every freelance developer should at least look at.</p>
<p>If you don&#8217;t know, the traditional way of pricing out a web development project (at least in my experience) is for a client to contact an agency (or freelancer), tell them what they want and the agency telling the client how much it&#8217;ll cost at a flat rate. There&#8217;s usually a back and forth over cost and features, time and expense, and shaving features accordingly to meet some predetermined budget, and there&#8217;s certainly a lot of minutia in between the parts, but those are the broad strokes (again, in my experience).</p>
<p>Every agency I&#8217;ve worked for and with, and every freelance project I&#8217;d previously taken on, had been priced using this model. From a client perspective it&#8217;s a winner; the client has an expectation of what a project will cost and the agency can manage expectations and allot resources accordingly. Considering most agencies have their employees on salary, where the employees make a set rate regardless of work, this can work out nicely for the agency, from a bottom line stand point, as well. When things go outside of scope, and they <em>will </em>go out of scope, your employees work more with no additional investment from a raw cost standpoint.</p>
<p>The obvious downside though is that the principals of a project, the people who actually <em>create</em> the damn property or concept, are treated as replaceable commodities. The effect this can have on morale within an agency can not be understated. But, and this is important, within an agency, that&#8217;s the <em>job</em>. In my opinion, that&#8217;s why good principals can easily make 6 figure salaries with sick benefits and bonuses; you get worked like a dog.</p>
<p>To be fair, I have heard stories of agencies where treating principals as disposable <em>isn&#8217;t</em> the norm but those are usually the smaller, boutique firms, and I haven&#8217;t had much experience with those.</p>
<p>In freelancing though this model doesn&#8217;t hold up even a little. There is no salary safety net. When a project goes out of scope, and again, it will go out of scope, you&#8217;re fucked as a freelancer. You&#8217;re no longer being paid without then negotiating for overages (which carries it&#8217;s own risk). Plainly, agreeing to a set price as a freelance web developer is a sure fire way to go hungry. Yet so many of us work that way it&#8217;s simply amazing, in hindsight, when I think about it.</p>
<p>The biggest challenge to charging hourly is actually finding clients who are willing to pay an hourly rate. It was pretty surprising to realize just how ingrained the project pricing model is within client&#8217;s expectations. Loads of potential clients <em>love </em>having a set price. That said, an unexpected benefit of the hourly model is that those clients who are willing to pay hourly are much more disciplined and knowledgeable about the medium and what&#8217;s in store. Simply, just having an hourly pricing model weeds out the ignorant and unrealistic clients. I found that it&#8217;s a nice way to keep the nonsense in check.</p>
<p>When I find a new client who&#8217;s willing to pay hourly (with a couple exceptions) the first thing I do is get a retainer. The retainer basically gives me the confidence in the client to be able to pay my rate, as well as giving me motivation to start work with the confidence of continued payment. Plus, if a client can&#8217;t, or won&#8217;t, pay the initial retainer than I know right away they aren&#8217;t worth working for. Harsh, maybe, but the initial retainer is important above and beyond the money involved. It shows respect and trust, and provides motivation for the work ahead. The retainer is only required up until trust is built; future projects don&#8217;t require it.</p>
<p>Once the retainer is agreed to, though not paid, the next thing to do is figure out how long it&#8217;s going to take to do what the client needs done. Basically, how much are things going to cost. This is where the process is very similar to the project pricing model; you still have to know ahead of time what&#8217;s expected so you can say how long it&#8217;ll cost. The big difference here though is that your estimate needs to be <em>flexible</em>. Instead of saying, and sticking to, a project will cost, for example. $15,000 you say it&#8217;ll take around 100 to 150 hours likely costing $10,000 to $15,000.</p>
<p>The &#8220;to 150&#8243; hours part above is important. <em>Always</em> overestimate. What I do is imagine how long something will take and then, seriously, multiply that by 3. For example, if I think a project would take me 50 hours I say it&#8217;ll take 150 hours. Why? Three reasons; shit changes, there&#8217;s more involved than just development, and experience has taught me that I, personally, <em>suck</em> at estimating timelines (I&#8217;m an optimist). You have to take into project design, account emails, phone calls, client visits, project management, quality assurance, and client hand holding. The back and forth can kill a budget but my time isn&#8217;t free; the client pays for all of that.</p>
<p>Plus, from a client relations stand point, being under budget is always a good thing. If you can get the client to expect, and agree to, a cost that&#8217;s more than expected, they&#8217;ll love you to death when their budget isn&#8217;t tapped.</p>
<p>This leaves the question of accountability. To make sure the client has the confidence in <em>me</em> to do what they need I&#8217;ve found it&#8217;s important to provide as detailed an accounting as possible for all hours worked. Everything gets documented and passed to the client with invoices. When I send an invoice for 60 hours you can bet there&#8217;s a breakdown of every single hour worked, what was done, on what project/task, and when. Honestly is critical. If a client decides to audit your invoices, and you need to defend what you&#8217;ve done, you <em>don&#8217;t </em>want to go head to head with someone who knows it shouldn&#8217;t take 40 hours to install the core of ExpressionEngine (for example).</p>
<p>In terms of deployment process I&#8217;m not a fan of holding projects hostage from a client. By this I mean, keeping the client from having access until payment is received. My thought is that if I have a client that requires this sort of shenanigans than they shouldn&#8217;t be my client. Even entertaining the idea is a red flag so when/if it does come up I try to recognize the end is near. Further, that&#8217;s just dirty pool in my opinion.</p>
<p>With all that said, to me, it&#8217;s a wonder why any freelance dev would ever opt for a project rate (outside of panic mode, &#8220;I need money NOW&#8221;, freaking out). It&#8217;s just a losing proposition and one that I&#8217;m glad is off my table.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2012/02/freelancing-and-the-hourly-rate/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>It Was Supposed To Be Just An Experiment&#8230;</title>
		<link>http://blog.ericlamb.net/2011/10/it-was-supposed-to-be-just-an-experiment/</link>
		<comments>http://blog.ericlamb.net/2011/10/it-was-supposed-to-be-just-an-experiment/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 01:21:42 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[CartThrob]]></category>
		<category><![CDATA[ExpressionEngine]]></category>
		<category><![CDATA[mithra62]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3768</guid>
		<description><![CDATA[Last June I decided to do something unprecedented for me; I dipped my toe into the ExpressionEngine add-on market to try and sell some custom add-ons I&#8217;d written. Being the open source loving hippie that I am this felt pretty out of character for me at the time and I got a bit of grief [...]]]></description>
			<content:encoded><![CDATA[<p>Last June I decided to do something unprecedented for me; I dipped my toe into the <a href="http://expressionengine.com/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2F','ExpressionEngine')" title="ExpressionEngine" target="_blank">ExpressionEngine</a> add-on market to try and sell some custom add-ons I&#8217;d written. Being the open source loving hippie that I am this felt pretty out of character for me at the time and I got a bit of grief for it from friends and my own id. But I&#8217;ve been talking about moving out of client services for far too long and figured a little experiment by writing some add-ons and selling them through <a href="http://devot-ee.com/" onclick="return TrackClick('http%3A%2F%2Fdevot-ee.com%2F','Devot%3Aee')" title="Devot:ee" target="_blank">Devot:ee</a> (the de facto marketplace for ExpressionEnigne add-ons) would be a good introduction into full time commercial development. Looking at things 4 months later I realize that deciding do that was one of most important things I could have done for my career.</p>
<div id="attachment_3777" class="wp-caption aligncenter" style="width: 367px"><a href="http://mithra62.com" onclick="return TrackClick('http%3A%2F%2Fmithra62.com','mithra62')"><img src="http://blog.ericlamb.net/wp-content/uploads/2011/10/mithra62_logo2.png" alt="mithra62" title="mithra62" width="357" height="185" class="size-full wp-image-3777" /></a><p class="wp-caption-text">mithra62</p></div>
<p>Those of you who read this blog regularly (which, I admit hasn&#8217;t been that regular of late) probably noticed that I&#8217;ve been writing more and more about <a href="http://blog.ericlamb.net/tag/expression-engine/" title="ExpressionEngine">ExpressionEngine</a> over the last year and a half. Obviously, I&#8217;ve been doing a lot of ExpressionEngine development. Mostly for client work but, like most things a good programmer does, I eventually built up a go to library of custom stuff for when new projects started. Just your normal stuff really; a couple extensions and modules to make my client&#8217;s lives easier and give that little &#8220;extra&#8221; to make a project sparkle. </p>
<p>Then, my <a href="http://blog.ericlamb.net/2011/05/cartthrob-2-0-beta-fun/" title="CartThrob 2.0 Beta Fun">CartThrob</a> project ended. This is a project that will forever have a place in my heart. Not the site specifically mind you, which is pretty awesome BTW, but the clients tight budget combined with needing more from the site than they had initially outlined created a dilemma that presented an opportunity. I could either hand off the site as is, which was to the client&#8217;s spec but not to their expectations, or I could continue working without getting paid to make the client happy. Then, a third option came to mind. </p>
<p>I proposed to the client that I build an add-on to handle their needs on the condition that I retain ownership of the add-on. The plan was simple; I&#8217;d write this add-on and then sell it on Devot:ee in the hopes that eventually I&#8217;d recoup my loss in time investment. Hence, the birth of my first commercial add-on now called <a href="http://mithra62.com/projects/view/ct-admin/" onclick="return TrackClick('http%3A%2F%2Fmithra62.com%2Fprojects%2Fview%2Fct-admin%2F','CT+Admin')" title="CT Admin" target="_blank">CT Admin</a>. That&#8230; I then sat on for a couple months while I worked up the courage to put it up for sale. </p>
<p>The more I thought about releasing CT Admin the more nervous I became over the prospect of putting out an add-on that&#8217;s only useful for users of another third party add-on. Starting out with a customer base that&#8217;s a small slice of another company&#8217;s customer base isn&#8217;t exactly a good way to measure an industry. So, I decided to release a second add-on around the same time as CT Admin. </p>
<p>This second add-on, now named <a href="http://mithra62.com/projects/view/backup-pro/" onclick="return TrackClick('http%3A%2F%2Fmithra62.com%2Fprojects%2Fview%2Fbackup-pro%2F','Backup+Pro')" title="Backup Pro" target="_blank">Backup Pro</a>, was at the time a specialized backup add-on I&#8217;d written for my hosted clients which due to certain configuration conflicts couldn&#8217;t use any of the existing ExpressionEngine backup add-ons on the market. Releasing Backup Pro was also a gamble though of a different sort; as mentioned there were existing add-ons within that niche and and one of those competitors has fiercely loyalty customers (Hi Tom!). But still, two add-ons are better than one. Right?</p>
<p>So on June 10th I had a stiff drink and posted my add-ons to Devot:ee. And a whole 24 hours later I sold my first add-on. Immediately, I realized I was in. I was hooked. The joy I felt when I got the email notification from Devot:ee about the sale was absolute and total. Someone had paid <em>me</em> money for proprietary code I had written that I was going to be able to sell again. Fuck. That was the sweetest $24 I ever made. </p>
<p>But $24 also came with a weird sense of responsibility I never really felt writing OSS code. With OSS I&#8217;d always kept things at my pace and, unless there was anything critical that affected me personally, individual issues other users experienced weren&#8217;t that big of a priority. But, with the ExpressionEngine add-ons, that someone had paid real cash money for, the paradigm shifted from random and faceless users to clients. In essence my customers became my clients and that&#8217;s a dynamic I&#8217;ve always been comfortable with in terms of knowing how to respond. Put simple; complete and total support until they&#8217;re happy. </p>
<p>And that&#8217;s really the key to everything right there. What initially started out as a small experiment I personally likened to an OSS project morphed into me sharing some responsibility with other developer&#8217;s client work. Shit got real all of a sudden. People were paying money on my code with the belief that the code would help them solve their client&#8217;s problems. For those users who had issues (and there were more than a few) my responsibility could not be denied. </p>
<p>Initially, I was naive enough to think I could just post my add-ons to Devot:ee and go about my life. I had no concept of how much care would have to go into support and customer satisfaction or the amount of hours I&#8217;d spend in the Devot:ee forums and answering questions on Twitter. To give an idea of just how many updates there have been; at the time of this writing Backup Pro is at version 1.8.1. That&#8217;s a lot of bug fixes and feature requests in just under 4 months. Almost to the point of ridiculousness. </p>
<p>But it&#8217;s addictive. Extremely so. The more feedback I got, and the more features and bugs that were fixed or added, the better the products became. The process creates a really nice positive feedback loop wherein we&#8217;re all winners. The customer gets a better product, I get to create a better product which, in turn, makes my products more appealing to others. It&#8217;s really something to be a part of. </p>
<p>So after 4 months of progressively improving my products, networking within the community, building a dedicated site for marketing and having an absurd advertising appetite and a library of 7 add-ons now, I look around and realize that I&#8217;m a part of something I had never anticipated; the ExpressionEngine community. And it feels like home.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/10/it-was-supposed-to-be-just-an-experiment/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stand Alone ExpressionEngine Authentication</title>
		<link>http://blog.ericlamb.net/2011/08/stand-alone-expressionengine-authentication/</link>
		<comments>http://blog.ericlamb.net/2011/08/stand-alone-expressionengine-authentication/#comments</comments>
		<pubDate>Mon, 08 Aug 2011 09:25:14 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ExpressionEngine]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3746</guid>
		<description><![CDATA[I had a small task come to me recently wherein a site needed to allow for verification of ExpressionEngine credentials but couldn&#8217;t use the normal controllers for access. The challenge was in how ExpressionEngine encrypts the passwords and replicating that behavior. Taking a look at the Login controllers made things very clear though; as usual [...]]]></description>
			<content:encoded><![CDATA[<p>I had a small task come to me recently wherein a site needed to allow for verification of ExpressionEngine credentials but couldn&#8217;t use the normal controllers for access. The challenge was in how ExpressionEngine encrypts the passwords and replicating that behavior. Taking a look at the Login controllers made things very clear though; as usual ExpressionEngine was very well written. </p>
<p>Here&#8217;s an example of how to do it (note that this will only work within the CP):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pass</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'members.password, members.unique_id, members.member_id, members.group_id, member_groups.can_access_cp'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'username'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'member_groups.site_id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">item</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'site_id'</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'members.group_id = '</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dbprefix</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'member_groups.group_id'</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #000;">&#40;</span><span style="color: #990000;">array</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'members'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'member_groups'</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>	
<span style="color: #22f;">if</span> <span style="color: #000;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">num_rows</span><span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">0</span><span style="color: #000;">&#41;</span>
<span style="color: #000;">&#123;</span>
	<span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> do_hash<span style="color: #000;">&#40;</span><span style="color: #000088;">$pass</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #22f;">if</span> <span style="color: #000;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">row</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'password'</span><span style="color: #000;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$password</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//good user credentials :)</span>
	<span style="color: #000;">&#125;</span>
	<span style="color: #22f;">else</span>
	<span style="color: #000;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//bad password/good username</span>
	<span style="color: #000;">&#125;</span>			
<span style="color: #000;">&#125;</span>
<span style="color: #22f;">else</span>
<span style="color: #000;">&#123;</span>
	<span style="color: #666666; font-style: italic;">//bad username</span>
<span style="color: #000;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>According to the site admin who passed this my way the above won&#8217;t work outside the CP. He was kind enough to send along an example that worked fine for their situation:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">library</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'auth'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadfile</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$authorized</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">auth</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">authenticate_username</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'username'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">EE</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'password'</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #22f;">if</span> <span style="color: #000;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #000088;">$authorized</span><span style="color: #000;">&#41;</span>
<span style="color: #000;">&#123;</span>
	set_status_header<span style="color: #000;">&#40;</span><span style="color: #cc66cc;">500</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">exit</span><span style="color: #000;">&#40;</span>lang<span style="color: #000;">&#40;</span><span style="color: #0000ff;">'unauthorized_request'</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/08/stand-alone-expressionengine-authentication/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Importing Legacy Users Into ExpressionEngine</title>
		<link>http://blog.ericlamb.net/2011/07/importing-legacy-users-into-expressionengine/</link>
		<comments>http://blog.ericlamb.net/2011/07/importing-legacy-users-into-expressionengine/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 12:17:11 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[ExpressionEngine]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3753</guid>
		<description><![CDATA[Fuck. We spent all this time convincing one of the oldest clients with the agency into upgrading their old and kludgy, PHP 3 era, nightmare website into a snazzy ExpressionEngine 2.2 gem of modern technology. But, like the assholes we are, we didn&#8217;t quite think through the fact that they have a complicated data structure [...]]]></description>
			<content:encoded><![CDATA[<p>Fuck. We spent all this time convincing one of the oldest clients with the agency into upgrading their old and kludgy, PHP 3 era, nightmare website into a snazzy ExpressionEngine 2.2 gem of modern technology. But, like the assholes we are, we didn&#8217;t quite think through the fact that they have a complicated data structure (having been built when PHP <em>really</em> sucked) that we&#8217;d have to import into ExpressionEngine. So, you know, fuck&#8230;</p>
<p>But then, after the pants come on and a moment to reflect is had and the obviousness of the overreaction becomes clear. This is ExpressionEngine after all; there&#8217;s bound to be some utility available to handle this with the least amount of pain possible. And there is: the <a title="ExpressionEngine Member Import Utility" href="http://expressionengine.com/user_guide/cp/tools/utilities/member_import/index.html" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Fuser_guide%2Fcp%2Ftools%2Futilities%2Fmember_import%2Findex.html','ExpressionEngine+Member+Import+Utility')" target="_blank">Member Import Utility</a> and, even better, it&#8217;s included into the core of ExpressionEngine so it&#8217;s already there.</p>
<p>And in traditional ExpressionEngine fashion its built in much the same and logical way most would design an import system. There are two different modes to work with: one to <a title="Import from XML" href="http://expressionengine.com/user_guide/cp/tools/utilities/member_import/import_from_xml.html" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Fuser_guide%2Fcp%2Ftools%2Futilities%2Fmember_import%2Fimport_from_xml.html','Import+from+XML')" target="_blank">import an ExpressionEngine Member XML file</a> and another to create said file from a <a title="Convert Delimited Data to XML" href="http://expressionengine.com/user_guide/cp/tools/utilities/member_import/convert_to_xml.html" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Fuser_guide%2Fcp%2Ftools%2Futilities%2Fmember_import%2Fconvert_to_xml.html','Convert+Delimited+Data+to+XML')" target="_blank">CSV formatted file</a>.</p>
<p>The CSV format conversion wasn&#8217;t really all that for the purposes of this project (mostly due to conditional rewriting of specific column entries) but it does have it&#8217;s uses. For instance, with smaller, self contained, exports it should be a snap to easily hand over the export straight from phpMyAdmin and convert it into an <a title="Member XML Format" href="http://expressionengine.com/user_guide/cp/tools/utilities/member_import/member_xml_format.html" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Fuser_guide%2Fcp%2Ftools%2Futilities%2Fmember_import%2Fmember_xml_format.html','Member+XML+Format')" target="_blank">ExpressionEngine Member XML</a> file. One big drawback though is that the CSV import doesn&#8217;t appear to create new custom member fields on import so manual mapping is required per import.</p>
<p>The flip side of the CSV format convertor is the straight ExpressionEngine Member XML import utility. The big drag with this, and only if you don&#8217;t use the CSV convertor, is that a script has to be written to handle the conversion. Not too big a deal but, considering most installations will vary, this is going to require manual intervention every time a new system is imported. But, unlike the CSV convertor, the Member XML importer does actually create missing custom fields so updating the system shouldn&#8217;t be too big  a drag.</p>
<p>For my purposes I wrote a dirty little script to create the XML file for me so it was simply a matter of importing. I&#8217;m lazy, in the long term, so keeping as much of this as simple as possible is always a priority for me. But, since it&#8217;s a throw away thing cleanliness and best practices is less important than getting me more time to do real work. A word of caution though; the XML parser within ExpressionEngine isn&#8217;t very helpful when it comes to error messages and telling you what went wrong. You will curse.</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
23
24
25
26
27
28
29
30
31
</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: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM users&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #22f;">if</span><span style="color: #000;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$result</span><span style="color: #000;">&#41;</span>
<span style="color: #000;">&#123;</span>
	<span style="color: #22f;">echo</span> <span style="color: #990000;">mysql_error</span><span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
<span style="color: #000;">&#125;</span>
<span style="color: #000088;">$ee</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&lt;members&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #22f;">while</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_assoc</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span>
<span style="color: #000;">&#123;</span>
	<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&lt;member&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;username&gt;&lt;![CDATA[&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'first_name'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'last_name'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;]]&gt;&lt;/username&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;screen_name&gt;&lt;![CDATA[&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'first_name'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'last_name'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;]]&gt;&lt;/screen_name&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;legacy_subscriber_id&gt;&lt;![CDATA[&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$row</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'subscriber_id'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;]]&gt;&lt;/legacy_subscriber_id&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #22f;">foreach</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #22f;">AS</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
		<span style="color: #22f;">if</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">''</span><span style="color: #000;">&#41;</span>
		<span style="color: #000;">&#123;</span>
			<span style="color: #22f;">continue</span><span style="color: #339933;">;</span>
		<span style="color: #000;">&#125;</span>
		<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$key</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&gt;&lt;![CDATA[&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;]]&gt;&lt;/&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$key</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000;">&#125;</span>
	<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&lt;/member&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000;">&#125;</span>
&nbsp;
<span style="color: #000088;">$ee</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/members&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #22f;">echo</span> <span style="color: #000088;">$ee</span><span style="color: #339933;">;</span>
<span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>The above code is fine if your existing database is cool but, and this is weird, ExpressionEngine goes full retard when it encounters anything it doesn&#8217;t like in the XML and won&#8217;t let you proceed. It&#8217;s really quite stunning. The XML importer knows that duplicate email addresses are bad in the database but instead of, say, allowing you to skip or force things the importer will just die and scream about a duplicate leaving you the only option of then manually pruning your data. Why they couldn&#8217;t be bothered with a checkbox or something allowing you to skip bad entries is beyond me but it makes the experience really, <em>really</em>, painful if your data sucks. </p>
<p>Still though, if your data is good to begin with the importer is a nice touch.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/07/importing-legacy-users-into-expressionengine/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Customizing ExpressionEngine 2.x Message Pages</title>
		<link>http://blog.ericlamb.net/2011/06/customizing-expressionengine-2-x-message-pages/</link>
		<comments>http://blog.ericlamb.net/2011/06/customizing-expressionengine-2-x-message-pages/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 07:00:47 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ExpressionEngine]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3718</guid>
		<description><![CDATA[An unfortunate issue with ExpressionEngine is how internal messaging is handled. It&#8217;s really unfortunate that such a nice platform like ExpressionEngine shows such a wart when it comes to managing system pages and templates. Anyone who&#8217;s ever had to modify the message pages can tell you; it&#8217;s a dirty and counter intuitive deed requiring a [...]]]></description>
			<content:encoded><![CDATA[<p>An unfortunate issue with <a href="http://expressionengine.com/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2F','ExpressionEngine')" title="ExpressionEngine" target="_blank">ExpressionEngine</a> is how internal messaging is handled. It&#8217;s really unfortunate that such a nice platform like ExpressionEngine shows such a wart when it comes to managing system pages and templates. Anyone who&#8217;s ever had to modify the message pages can tell you; it&#8217;s a dirty and counter intuitive deed requiring a lack of best practices that will leave you feeling pretty gross. </p>
<div id="attachment_3736" class="wp-caption aligncenter" style="width: 639px"><img src="http://blog.ericlamb.net/wp-content/uploads/2011/06/ee_default_message2.jpg" alt="Customizing ExpressionEngine 2.x Message Pages" title="Customizing ExpressionEngine 2.x Message Pages" width="629" height="130" class="size-full wp-image-3736" /><p class="wp-caption-text">Customizing ExpressionEngine 2.x Message Pages</p></div>
<p>The current method of modifying the message pages works as you would expect; this being an ExpressionEngine site you just go to the Design section and you&#8217;ll find them under &#8220;Message Pages&#8221; . There are 3 different types of message pages you can edit (Email Notifications, User Messages and Offline Template) and while it would seem logical on how what to do to get going you&#8217;d probably be wrong (if you hadn&#8217;t ever tried before). There are a couple problems here&#8230;</p>
<p>First, you can&#8217;t use EE template tags within those templates. It&#8217;s the damnedest thing too because some of those templates (User Messages and Email Notifications) do allow <em>specific</em> tags; they just don&#8217;t parse any others. So, if you&#8217;re a good little programmer and you build your site using global embeds for building your templates (head &#038; footer for example) you&#8217;re hosed. Your only option is to hard code your HTML which, if you&#8217;ve built even a simple site, you&#8217;ll instantly be filled with remorse and guilt over creating such a maintenance nightmare. </p>
<p>Second, and after the above it&#8217;s a minor issue though if you&#8217;re good enough for the above to be an issue this&#8217;ll probably piss you off too; you can&#8217;t save those templates as files. This means version control is going to be a bit of a problem. After nearly 10 years of having version control beat into me this hurt pretty bad. To be honest, because of tight deadline and even tighter budgets I could have lived with the guilt and shame of hard coding just to finish the project but taking away my version control was like adding insult to injury. </p>
<p>It&#8217;s quite the head scratcher when you get right down to it; a smart and clever company redesigns their entire product from the ground up and completely drops the ball when it comes to the messaging system. It&#8217;s a shame&#8230;</p>
<p>There is another option though it does require money; a really nice extension called <a title="Custom System Messages" href="http://devot-ee.com/add-ons/custom-system-messages/" onclick="return TrackClick('http%3A%2F%2Fdevot-ee.com%2Fadd-ons%2Fcustom-system-messages%2F','Custom+System+Messages')" target="_blank">Custom System Messages</a>. The extension was written by <a href="http://devot-ee.com/developers/brian-litzinger/" onclick="return TrackClick('http%3A%2F%2Fdevot-ee.com%2Fdevelopers%2Fbrian-litzinger%2F','Brian+Litzinger')" title="Brian Litzinger" target="_blank">Brian Litzinger</a> and is available for $12 through the ExpressionEngine marketplace <a href="http://devot-ee.com/" onclick="return TrackClick('http%3A%2F%2Fdevot-ee.com%2F','Devot%3Aee')" title="Devot:ee" target="_blank">Devot:ee</a>.</p>
<div id="attachment_3738" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.ericlamb.net/wp-content/uploads/2011/06/custom_system_message.jpg" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2Fwp-content%2Fuploads%2F2011%2F06%2Fcustom_system_message.jpg','Custom+System+Messages')"><img src="http://blog.ericlamb.net/wp-content/uploads/2011/06/custom_system_message-300x139.jpg" alt="Custom System Messages" title="Custom System Messages" width="300" height="139" class="size-medium wp-image-3738" /></a><p class="wp-caption-text">Custom System Messages</p></div>
<p>Custom System Messages works exactly as you would expect ExpressionEngine to work; through a nice interface you choose custom templates for specific messages. You can set a different template for both message scenarios (General Error and Form Submission Error) as well as change the behavior of the {link} template tag so it doesn&#8217;t use the lame ass JavaScript &#8220;back link&#8221;. </p>
<p>The best part though is that Custom System Messages allows you to set special templates based off of all the actions your site has (even those from other modules and extensions). So, for example, if you have a CartThrob site you can set a special template for when adding an item to your cart fails and separate template for when updating an item within a cart fails. It&#8217;s really quite slick and for only $12 it&#8217;s very reasonable. Priced just enough to dissuade any developer from rolling their own solution. </p>
<p>I do have to say how disappointing it is to see ExpressionEngine lacking this built in. To me, it&#8217;s reminiscent of buying a car and being charged extra for the gas cap. Sure, I can just go buy a gas cap for a couple bucks but it really should be a part of the car to begin with. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/06/customizing-expressionengine-2-x-message-pages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connect to Multiple Databases with Zend Framework</title>
		<link>http://blog.ericlamb.net/2011/05/connect-to-multiple-databases-with-zend-framework/</link>
		<comments>http://blog.ericlamb.net/2011/05/connect-to-multiple-databases-with-zend-framework/#comments</comments>
		<pubDate>Tue, 31 May 2011 07:00:54 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3614</guid>
		<description><![CDATA[I recently had a project where there would be 2 databases being used together; one locally and the other hosted externally by the client. Using traditional PHP this wouldn&#8217;t be a problem (just pass a link to the database I want to use on a per query basis and I&#8217;m done), but, since this project [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had a project where there would be 2 databases being used together; one locally and the other hosted externally by the client. Using traditional PHP this wouldn&#8217;t be a problem (just pass a link to the database I want to use on a per query basis and I&#8217;m done), but, since this project was to use the <a title="Zend Framework" href="http://framework.zend.com/" onclick="return TrackClick('http%3A%2F%2Fframework.zend.com%2F','Zend+Framework')" target="_blank">Zend Framework</a> and I&#8217;d never attempted this sort of thing before with it, I was in quite the pickle.</p>
<p>Doing some quick Googling turned up an article that seemed to fit the bill: <a title="Zend Framework: Connecting to 2 databases" href="http://blog.ekini.net/2009/03/04/zend-framework-connecting-to-2-databases/" onclick="return TrackClick('http%3A%2F%2Fblog.ekini.net%2F2009%2F03%2F04%2Fzend-framework-connecting-to-2-databases%2F','Zend+Framework%3A+Connecting+to+2+databases')" target="_blank">Zend Framework: Connecting to 2 databases</a> written by <a title="Wenbert Del Rosario" href="http://blog.ekini.net/" onclick="return TrackClick('http%3A%2F%2Fblog.ekini.net%2F','Wenbert+Del+Rosario')" target="_blank">Wenbert Del Rosario</a>. Unfortunately though, while it was a good read and very informative, my circumstances were a little different. The database I had to connect to was hosted on an external network that I wouldn&#8217;t have local access to. I had to go over the wide Internet to connect. Using Wenbert&#8217;s tutorial would entail a constant connection on every request whether it needed it or not and that just wouldn&#8217;t do.</p>
<p>Anyone who&#8217;s ever had to connect to an external database can tell you it&#8217;s far from an ideal scenario. The latency involved with this strategy is noticeable and caching is pretty much required for any sane strategy. Still, Wenbert&#8217;s article was definitely helpful for developing my strategy.</p>
<p>As in Wenbert&#8217;s article I started with putting the connection information into my config.ini file</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//config.ini</span>
resources<span style="color: #339933;">.</span>db<span style="color: #339933;">.</span>adapter <span style="color: #339933;">=</span> PDO_MYSQL
resources<span style="color: #339933;">.</span>db<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>host <span style="color: #339933;">=</span> localhost
resources<span style="color: #339933;">.</span>db<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>username <span style="color: #339933;">=</span> <span style="color: #339933;">****</span>
resources<span style="color: #339933;">.</span>db<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>password <span style="color: #339933;">=</span> <span style="color: #339933;">****</span>
resources<span style="color: #339933;">.</span>db<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>dbname <span style="color: #339933;">=</span> local_db 
&nbsp;
externaldb<span style="color: #339933;">.</span>adapter <span style="color: #339933;">=</span> PDO_MYSQL
externaldb<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>host <span style="color: #339933;">=</span> example<span style="color: #339933;">.</span>com
externaldb<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>username <span style="color: #339933;">=</span> <span style="color: #339933;">****</span>
externaldb<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>password <span style="color: #339933;">=</span> <span style="color: #339933;">****</span>
externaldb<span style="color: #339933;">.</span>params<span style="color: #339933;">.</span>dbname <span style="color: #339933;">=</span> external_db</pre></div></div>

<p>Then, I created a standard Zend_Db_Table class that handled the connection:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">//Model/DbTable/External.php</span>
<span style="color: #666666; font-style: italic;">//name made up to protect the client but do yourself a favor and name your shit logically</span>
<span style="color: #000000; font-weight: bold;">class</span> Model_DbTable_External <span style="color: #000000; font-weight: bold;">extends</span> Model_DbTable_Abstract
<span style="color: #000;">&#123;</span>
   <span style="color: #009933; font-style: italic;">/**
     * Doesn't matter for use but ZF demands a $_name variable
     * @var string
     */</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;content&quot;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
		<span style="color: #000088;">$settings</span> <span style="color: #339933;">=</span> Zend_Registry<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'settings'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span> <span style="color: #339933;">=</span> Zend_Db<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$settings</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'externaldb'</span><span style="color: #000;">&#93;</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'adapter'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$settings</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'externaldb'</span><span style="color: #000;">&#93;</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'params'</span><span style="color: #000;">&#93;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000;">&#125;</span>
<span style="color: #000;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>With the above out of the way I can now connect to the external database. I just have to pipe all my SQL through the above class. To that end, and to provide a nice wrapper for the caching, I create a Model that has methods for all the SQL my app will need:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> Model_External <span style="color: #000000; font-weight: bold;">extends</span> Model_Abstract
<span style="color: #000;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * The key to use for the cache items
	 * @var string
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$cache_key</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'external_db'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
		parent<span style="color: #339933;">::</span>__construct<span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Model_DbTable_External<span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">;</span>
	<span style="color: #000;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testSystem<span style="color: #000;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
		<span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$cache_key</span><span style="color: #339933;">.</span><span style="color: #009900; font-weight: bold;">__FUNCTION__</span><span style="color: #339933;">.</span><span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
		<span style="color: #22f;">if</span><span style="color: #000;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$key</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span> 
		<span style="color: #000;">&#123;</span>	
			<span style="color: #666666; font-style: italic;">//just a random query with joins and whatnots to show  it's possible :)</span>
			<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #000;">&#40;</span><span style="color: #990000;">array</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'e'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'example_table1'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'e.id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'e.title'</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'e.id = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #000;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">limit</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'6'</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchAll</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cache_key</span><span style="color: #000;">&#41;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000;">&#125;</span>
		<span style="color: #22f;">return</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
	<span style="color: #000;">&#125;</span>
<span style="color: #000;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>So, using the above class I&#8217;ve abstracted out the SQL and provided caching through the below class Model_Abstract:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">//models/Abstract.php</span>
abstract <span style="color: #000000; font-weight: bold;">class</span> Model_Abstract
<span style="color: #000;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * The database object
	 * @var object
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$db</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * The Cache Object
	 * @var object
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$cache</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * The stored cache name
	 * @var string
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$cache_key</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
		<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Model_Cache<span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">// getting a Zend_Cache_Core object</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cache</span> <span style="color: #339933;">=</span> Zend_Cache<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #000;">&#40;</span>
	                    <span style="color: #0000ff;">'Core'</span><span style="color: #339933;">,</span>
	                    <span style="color: #0000ff;">'File'</span><span style="color: #339933;">,</span>
	                    <span style="color: #990000;">array</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'lifetime'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">720</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'automatic_serialization'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #000;">&#41;</span><span style="color: #339933;">,</span>
	                    <span style="color: #990000;">array</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'cache_dir'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'/path/to/cache/'</span><span style="color: #000;">&#41;</span>
		<span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>		
	<span style="color: #000;">&#125;</span>
<span style="color: #000;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Putting it all together I now have a mechanism to connect to an external database, perform queries against said database and can cache the results pretty easily and with minimal code. One of the advantages of this approach is that connections to the database only happen when needed instead of on every page request as in Wenbert&#8217;s article. So, for example, so long as the cached items exist then no database connection is created and no latency (outside of hitting the filesystem of course) is created.</p>
<p>Still though, there are ways to improve on this approach. For example, using APC instead of the file system for the caching would help as would increasing the cache lifetime from 2 hours to something more but, overall, the above should be a good starting point. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/05/connect-to-multiple-databases-with-zend-framework/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CartThrob 2.0 Beta Fun</title>
		<link>http://blog.ericlamb.net/2011/05/cartthrob-2-0-beta-fun/</link>
		<comments>http://blog.ericlamb.net/2011/05/cartthrob-2-0-beta-fun/#comments</comments>
		<pubDate>Thu, 26 May 2011 22:00:58 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[CartThrob]]></category>
		<category><![CDATA[e-commerce]]></category>
		<category><![CDATA[ExpressionEngine]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3668</guid>
		<description><![CDATA[About a year ago I reviewed various shopping cart platforms for what was to be an &#8220;upcoming&#8221; project. After numerous delays and client hand holding (with the requisite back and forth) one year later that project finally began. And, as has lately become a trend in my professional life, the client&#8217;s spec combined with a [...]]]></description>
			<content:encoded><![CDATA[<p>About a year ago I reviewed various <a title="Should We Use Prestashop" href="http://blog.ericlamb.net/2010/05/should-we-use-prestashop/" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fshould-we-use-prestashop%2F','Should+We+Use+Prestashop')">shopping</a> <a title="Should We Use OpenCart" href="http://blog.ericlamb.net/2010/05/should-we-use-opencart/" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fshould-we-use-opencart%2F','Should+We+Use+OpenCart%3F')" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fshould-we-use-opencart%2F','Should+We+Use+OpenCart')">cart</a> <a title="A Closer Look At Avactis" href="http://blog.ericlamb.net/2010/05/a-closer-look-at-avactis/" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fa-closer-look-at-avactis%2F','A+Closer+Look+At+Avactis')" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fa-closer-look-at-avactis%2F','A+Closer+Look+At+Avactis')">platforms</a> for what was to be an &#8220;upcoming&#8221; project. After numerous delays and client hand holding (with the requisite back and forth) one <em>year </em>later that project finally began. And, as has lately become a trend in my professional life, the client&#8217;s spec combined with a drastically shortened and accelerated deadline forced us to go with something completely unknown and with only cursory inspection; the 3rd party e-commerce <a title="ExpressionEngine" href="http://expressionengine.com/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2F','ExpressionEngine')" target="_blank">ExpressionEngine</a> module <a title="CartThrob" href="http://cartthrob.com/" onclick="return TrackClick('http%3A%2F%2Fcartthrob.com%2F','CartThrob+Logo')" onclick="return TrackClick('http%3A%2F%2Fcartthrob.com%2F','CartThrob')" target="_blank">CartThrob 2.0</a> (beta at the time of this review BTW).</p>
<div id="attachment_3689" class="wp-caption aligncenter" style="width: 342px"><a title="CartThrob Logo" href="http://cartthrob.com/" onclick="return TrackClick('http%3A%2F%2Fcartthrob.com%2F','CartThrob+Logo')" onclick="return TrackClick('http%3A%2F%2Fcartthrob.com%2F','CartThrob')" target="_blank"><img class="size-full wp-image-3689" title="CartThrob" src="http://blog.ericlamb.net/wp-content/uploads/2011/05/cartthrob_logo.png" alt="CartThrob" width="332" height="117" /></a><p class="wp-caption-text">CartThrob</p></div>
<p>Of course this presented the problem of actually using an unknown  package to build a site with. Thankfully though, while CartThrob has a  steep learning curve and is most certainly missing key functionality,  it&#8217;s an overall nice package that allowed us to do what we needed. Sure, there&#8217;s pain involved (lots of configuration, testing and set up) but with a little elbow grease it all worked out.</p>
<p>As mentioned, CartThrob is an ExpressionEngine module for managing an online store. It&#8217;s available for both ExpressionEngine branches (1.x and 2.x) and was voted <a href="http://devot-ee.com/academee-awards/2010/" onclick="return TrackClick('http%3A%2F%2Fdevot-ee.com%2Facademee-awards%2F2010%2F','Module+of+the+Year+by+Devot%3Aee+in+2010')" target="_blank">Module of the Year by Devot:ee in 2010</a> (for the 1.x version only). This being an ExpressionEngine project CartThrob would, in theory, be a nice fit.</p>
<p>One of the really nice things about using CartThrob is that it uses the ExpressionEngine admin panel for managing your store. This meant there wouldn&#8217;t be a second administration site that the client would have to learn. (Personally, I always found dual admins to be janky at best and sloppy/lazy at worst so this was a definite bonus in favor CartThrob.)</p>
<p>But this is also double edged because, well, pretty much everything about your store is saved into the entries system within ExpressionEngine. This, of course, causes your Entries panel to become an eye sore whenever you have to do anything there. Instead of having a dedicated section to manage products you use the Entries section. Instead of a dedicated section to manage your orders you use the Entries section. Instead of a dedicated section to manage&#8230; well, you get the idea; everything is managed through the entries. This makes sense for the product management but when you have to dig through entries to find orders and coupons and discounts (etc) things get a little jarring for some people (even internally with my team) so it&#8217;s a concern.</p>
<p>Still, <em>single freaking admin</em> so it was kind of a lesser evil compromise.</p>
<p>The unusual thing though is that, for how thoroughly the management of items was punted (though, to be fair, it looks to be a feature versus bug debate more than &#8220;punting&#8221;), CartThrob has an extremely deep configuration section where you can customize CartThrob to function just right. CartThrob has all the basic customization functionality one would expect from any modern shopping cart platform (tax, shipping, payments with lots of merchant options, etc) plus a bunch of settings just to get CartThrob working (CartThrob is NOT an out of the box solution). It&#8217;s all presented in an easy to use interface that&#8217;s designed to mesh with the ExpressionEngine administration panel design which makes for an easier experience.</p>
<p>As far as merchant accounts go (for accepting payments through your site) there&#8217;s the usual suspects of <a title="Authorize.net" href="http://www.authorize.net/" onclick="return TrackClick('http%3A%2F%2Fwww.authorize.net%2F','Authorize.net')" target="_blank">Authorize.net</a>, <a title="Paypal" href="http://www.paypal.com/" onclick="return TrackClick('http%3A%2F%2Fwww.paypal.com%2F','Paypal')" target="_blank">Paypal</a> and <a title="SagePay" href="http://www.sagepay.com/" onclick="return TrackClick('http%3A%2F%2Fwww.sagepay.com%2F','SagePay')" target="_blank">SagePay</a> built right in but also some offline solutions for pay by check and credit accounts. For this project we used Authorize.net which went smooth for the most part but I can&#8217;t speak for the other options though if they&#8217;re anything like the Authorize.net one they&#8217;re probably cool. CartThrob also includes some extensions and hooks so writing your own payment gateway is possible if you need.</p>
<p>CartThrob can also hook into the ExpressionEngine member module so your customers can be registered internally. Like pretty much everything else with CartThrob there&#8217;s a bit of configuration involved to get it up and working though. Unfortunately though, there&#8217;s not really any out of the box functionality for your members to take advantage of. For example, there isn&#8217;t any way for your customers to view their past orders when logged in and when using the control panel and viewing a member&#8217;s profile there&#8217;s no relationship with CartThrob. You&#8217;re gonna have to write all that stuff yourself but, and I don&#8217;t know why, but CartThrob doesn&#8217;t store any relationships between ExpressionEngine members and it&#8217;s customers so expect a challenge.</p>
<p>In terms of the user side, the actual storefront, everything is done using ExpressionEngine templates and <a href="http://cartthrob.com/docs/tags/" onclick="return TrackClick('http%3A%2F%2Fcartthrob.com%2Fdocs%2Ftags%2F','CartThrob+Template+Tags')" title="CartThrob Template Tags" target="_blank">template tags</a>. There are lots of module methods available and even though it&#8217;s far from a complete package of the expected functionality. In fact, on our team, we got into a habit of thinking of CartThrob as a Lego set for <em>creating</em> what we want instead of <em>having</em> what we want already.</p>
<p>For example, to view the details about a users cart you&#8217;d use the template code below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000;">&#123;</span><span style="color: #990000;">exp</span><span style="color: #339933;">:</span>cartthrob<span style="color: #339933;">:</span>cart_info<span style="color: #000;">&#125;</span>
	<span style="color: #000;">&#123;</span>total_items<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>total_unique_items<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>cart_entry_ids<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>cart_shipping<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>cart_tax_rate<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>cart_tax<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>cart_subtotal<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
	<span style="color: #000;">&#123;</span>cart_total<span style="color: #000;">&#125;</span> <span style="color: #339933;">&lt;</span>br <span style="color: #339933;">/&gt;</span>
<span style="color: #000;">&#123;</span><span style="color: #339933;">/</span><span style="color: #990000;">exp</span><span style="color: #339933;">:</span>cartthrob<span style="color: #339933;">:</span>cart_info<span style="color: #000;">&#125;</span></pre></div></div>

<p>On the surface this appears to be nice because it keeps things within the core ExpressionEngine development process. And it would be except, well, CartThrob isn&#8217;t abstract enough. Too many times I would try to do something that seemed obvious, like <a href="http://cartthrob.com/forums/viewthread/2391/" onclick="return TrackClick('http%3A%2F%2Fcartthrob.com%2Fforums%2Fviewthread%2F2391%2F','How+to+build+a+logical+checkout+process')" title="How to build a logical checkout process" target="_blank">checking for shippable items within a users cart</a>, and would come up short; that functionality doesn&#8217;t exist. </p>
<p>Still though, don&#8217;t get me wrong. Yes, some of the above sucks. Absolutely. But CartThrob is still under development. Plus, since it&#8217;s a commercial script ($99) there&#8217;s financial incentive to improve it. And, truth be told, for as painful as certain points were it&#8217;s still way more fun to build a site with CartThrob than most of the other options I&#8217;ve used or reviewed like <a href="http://blog.ericlamb.net/2010/05/should-we-use-opencart/" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fshould-we-use-opencart%2F','Should+We+Use+OpenCart%3F')" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fshould-we-use-opencart%2F','Should+We+Use+OpenCart')" title="Should We Use OpenCart?">OpenCart</a> or <a href="http://blog.ericlamb.net/2010/05/a-closer-look-at-avactis/" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fa-closer-look-at-avactis%2F','A+Closer+Look+At+Avactis')" onclick="return TrackClick('http%3A%2F%2Fblog.ericlamb.net%2F2010%2F05%2Fa-closer-look-at-avactis%2F','A+Closer+Look+At+Avactis')" title="A Closer Look At Avactis">Avactis</a>. </p>
<p>Plus, again, <em>single freaking admin</em>!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/05/cartthrob-2-0-beta-fun/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ExpressionEngine and the Mystery of M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr</title>
		<link>http://blog.ericlamb.net/2011/05/expressionengine-and-the-mystery-of-m00o93h7pq09l8x1t49chy01z5j4tt91fgfr/</link>
		<comments>http://blog.ericlamb.net/2011/05/expressionengine-and-the-mystery-of-m00o93h7pq09l8x1t49chy01z5j4tt91fgfr/#comments</comments>
		<pubDate>Tue, 03 May 2011 11:53:21 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ExpressionEngine]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3651</guid>
		<description><![CDATA[Recently, I came across a weird issue while developing an ExpressionEngine 2.0 module. The issue was that, for some reason, my module would output a random string instead of the intended content. For example, instead of displaying the HTML, that the module created, the module would display the string M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr instead. Tracking down this issue [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I came across a weird issue while developing an <a title="ExpressionEngine" href="http://expressionengine.com/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2F','ExpressionEngine')" target="_blank">ExpressionEngine</a> 2.0 module. The issue was that, for some reason, my module would output a random string instead of the intended content. For example, instead of displaying the HTML, that the module created, the module would display the string M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr instead. Tracking down this issue was symptomatic of the proverbial needle in a haystack but I learned a lot about how ExpressionEngine&#8217;s internals work and was once again reminded to be pragmatic about my development strategies.</p>
<div id="attachment_3655" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.flickr.com/photos/rafaelm/145958282/" onclick="return TrackClick('http%3A%2F%2Fwww.flickr.com%2Fphotos%2Frafaelm%2F145958282%2F','random%2C+the+lion')"><img class="size-medium wp-image-3655" title="random, the lion" src="http://blog.ericlamb.net/wp-content/uploads/2011/05/random_the_lion-300x225.jpg" alt="random, the lion" width="300" height="225" /></a><p class="wp-caption-text">random, the lion</p></div>
<p>My first and automatic reaction when coming up against some random and meaningless output string is to just Google it and see what happens. Unfortunately though, this particular search, at the time at least, returned around 35,000 sites that were outputting the string and only 1 that had a <a title="Out from plugin getting over-written by EE?" href="http://expressionengine.com/archived_forums/viewthread/123475/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Farchived_forums%2Fviewthread%2F123475%2F','Out+from+plugin+getting+over-written+by+EE%3F')" target="_blank">reference to the issue with a possible explanation</a>. All of a a sudden this became an actual thing.</p>
<p>Putting aside the fact that there are around 35,000 sites with the string within Google for the moment (and that&#8217;s really a problem to be discussed) it took a bunch of digging but I finally found a few things:</p>
<p>First, this is an issue that has been within ExpressionEngine for <em>years.</em> Doing a <a title="ExpressionEngine Forum Search" href="http://expressionengine.com/archived_forums/search/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Farchived_forums%2Fsearch%2F','ExpressionEngine+Forum+Search')" target="_blank">search</a> on the ExpressionEngine site lists the first entry of this string at <a title="EE1.6 upgrade - Hash values apppearing throughout site" href="http://expressionengine.com/archived_forums/viewthread/54903/" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Farchived_forums%2Fviewthread%2F54903%2F','EE1.6+upgrade+-+Hash+values+apppearing+throughout+site')" target="_blank">2007</a> (sorry for the lack of a link; ExpressionEngine search is cached so old search URLs don&#8217;t work sometimes). My initial reaction was that this was kind of sloppy; EllisLab updated ExpressionEngine to 2.0 recently, from the ground up to use <a title="CodeIgniter" href="http://codeigniter.com/" onclick="return TrackClick('http%3A%2F%2Fcodeigniter.com%2F','CodeIgniter')" target="_blank">CodeIgniter</a> I believe, yet this issue got ported over?</p>
<p>After doing further research though, I came to believe the above is more to do with the design of ExpressionEngine than anything else like copying code. Turns out, there&#8217;s some logic to that random and oblique string.</p>
<p>Basically, that string (M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr) is a template holder for the content you want to output. It&#8217;s a little complicated in how it works but thanks to <a title="Explanation of EE Template Parsing" href="http://expressionengine.com/archived_forums/viewthread/85160/#j1" onclick="return TrackClick('http%3A%2F%2Fexpressionengine.com%2Farchived_forums%2Fviewthread%2F85160%2F%23j1','Explanation+of+EE+Template+Parsing')" target="_blank">Derek Jones over at the ExpressionEngine forums</a> there&#8217;s a succinct, though still a little complicated but less complicated than I could explain it, explanation of what&#8217;s going on.</p>
<blockquote><p>
&#8230;</p>
<p>The template parser is an extremely complex gizmo, so let me try to explain it stripped of what techno mumbo jumbo I can. This will still be long, so bear with me.</p>
<p>The template parser intelligently saves on resources by only processing a given tag once, no matter how many times it occurs on the template.  This means that if your tag is exactly the same, including its tagdata, EE only execute’s that modules code once, and replaces all copies of that tag with the output.</p>
<p>So first, when the template parser goes through the template finding tags, it replaces them all with temporary markers (the gibberish), and adds each tag to a list of tags to be parsed, in the order they are encountered on the template, top down.  Each marker starts with the letter “M” followed by the number (starting at 0) that tag is sitting in on The List.</p>
<p>Second, the parser goes down its list of tags.  It parses tag #0, and then replaces all of #0’s marker with that tag’s output.</p>
<p>——————-</p>
<p>Ok that’s the setup.  Here’s why it affected you, and why this side effect is not a problem (and also extremely, extremely rare). Remember, top down, tags will be assigned 0, 1, 2, etc.  So I’m abstracting it out to show the nesting and the positioning only.  Just focus on the numbers.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">{exp:tag0}foo{/exp:tag0}
{exp:tag1}
    bar
    {exp:tag0}foo{/exp:tag0}
{/exp:tag1}</pre></div></div>

<p>Step 1, the tags are grabbed and replaced with markers.  The first tag encountered is replaced first.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">M0
{exp:tag1}
    bar
    M0
{/exp:tag1}</pre></div></div>

<p>And then the next tag:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">M0
M1</pre></div></div>

<p>All tags have been collected and put on The List, so step 2, the parser goes down The List, and parses tag #0:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">foo
M1</pre></div></div>

<p>See the problem?  The second M0 is sitting protected inside the marker for tag #1, so it doesn’t get replaced.  Then tag #1 gets parsed.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">foo
    bar
    M0</pre></div></div>

<p>And the marker is left in the output.  EE doesn’t go back and parse tag #0 again, it’s already done that once, and will not do it again.</p>
<p>So the circumstances required for this problem to exist each are uncommon, and combined, very very rare:</p>
<p>1) Multiple exact copies of a given tag<br />
2) One or more copies nested inside another tag (tag nesting itself is also rare, and usually not recommended)<br />
3) The tag of which there are copies must sit at a position in the template above any occurrences of it being nested in another tag.
</p></blockquote>
<p>From the above it was easy to conclude that the template parsing stuff was breaking down in my module. Why, I had no idea, but at least I had a known starting point. While it was easy to conclude that my issue lay with the template parsing though, it was 100% off point for my particular issue which had to do with, of all things, the case of the module name. But, I digress. </p>
<p>The point is that for years now, and through multiple versions and rewrites, ExpressionEngine has consistently carried the same &#8220;issue&#8221;. Understanding the intent of the design for the template parsing helps put some perspective on things: it&#8217;s definitely a side effect of the particular approach. It bugged, and surprised, me that ExpressionEngine would have such oblique and useless output on such a widespread basis (35,000 site&#8217;s with that string within Google is a bit much in my opinion) but the more I thought about it the more I came to understand the complexity of what was involved in being helpful when the issue cropped up. Aside from abandoning the approach what could really be done?</p>
<p>It&#8217;s a nice reminder that development is often a balancing act between getting what you want and dealing with a counter issue. The ExpressionEngine team developed a strategy to enable them to effectively and efficiently meet their requirements but there&#8217;s sometimes an issue; a random string gets output instead of the template data. Plus, since the cause could be for anything from bad module installation data (as I had) to an issue within a template there&#8217;s no real way to provide helpful error messages when the template parsing does fail. But, on the other hand, the template parser does exactly what it was designed to do (and it does it well). </p>
<p>Which would you choose?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/05/expressionengine-and-the-mystery-of-m00o93h7pq09l8x1t49chy01z5j4tt91fgfr/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>3 Lines of Code&#8230;</title>
		<link>http://blog.ericlamb.net/2011/04/3-lines-of-code/</link>
		<comments>http://blog.ericlamb.net/2011/04/3-lines-of-code/#comments</comments>
		<pubDate>Sat, 16 Apr 2011 04:32:00 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[wp-click-track]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3643</guid>
		<description><![CDATA[I just pushed an update to the WordPress plugin repository for the latest update to Wp-Click-Track. It&#8217;s been around 9 months since I&#8217;ve had a chance to even look at my own stats with Wp-Click-Track much less fix a couple bugs that have cropped up since but I finally found the time. And then, after [...]]]></description>
			<content:encoded><![CDATA[<p>I just pushed an update to the WordPress plugin repository for the latest update to Wp-Click-Track. It&#8217;s been around 9 months since I&#8217;ve had a chance to even look at my own stats with <a title="Wp-Click-Track" href="http://blog.ericlamb.net/projects/wp-click-track/">Wp-Click-Track</a> much less fix a couple bugs that have cropped up since but I finally found the time. And then, after spending 10 whole minutes looking into the cause of a couple bugs when I found that 3 lines of code fixed all of them.</p>
<p>3 little lines of code to fix the timezone bug, disappearing stats bug and random timestamp issues.</p>
<p>Also, please keep in mind that Wp-Click-Track is a labor of love; I work full time as a freelance programmer and try to keep a healthy social life so sometimes my priorities are a little wacked. Point being, I try to stay on top of these things but sometimes life gets in the way. But, I will get to it I can promise that.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/04/3-lines-of-code/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Custom Routes With Zend Framework</title>
		<link>http://blog.ericlamb.net/2011/04/custom-routes-with-zend-framework/</link>
		<comments>http://blog.ericlamb.net/2011/04/custom-routes-with-zend-framework/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 18:43:58 +0000</pubDate>
		<dc:creator>Eric Lamb</dc:creator>
				<category><![CDATA[Brain Dump]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.ericlamb.net/?p=3609</guid>
		<description><![CDATA[When I first started using the Zend Framework I didn&#8217;t give much thought into the way it handles routing URLs to the controllers/action combo. Honestly, while I had become used to so called search engine friendly, or pretty, URLs, I grew up on query strings where the idea of URLs was more about function than [...]]]></description>
			<content:encoded><![CDATA[<p>When I first started using the <a href="http://framework.zend.com/" onclick="return TrackClick('http%3A%2F%2Fframework.zend.com%2F','Zend+Framework')" title="Zend Framework" target="_blank">Zend Framework</a> I didn&#8217;t give much thought into the way it handles routing URLs to the controllers/action combo. Honestly, while I had become used to so called search engine friendly, or pretty, URLs, I grew up on query strings where the idea of URLs was more about function than form. So when I moved over to Zend Framework as a framework I didn&#8217;t give a damn how the URLs were parsed and routed to which controller/action. I just accepted the natural order of things. </p>
<div id="attachment_3627" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.flickr.com/photos/orudge/5602610471/lightbox/#/photos/orudge/5602610471/" onclick="return TrackClick('http%3A%2F%2Fwww.flickr.com%2Fphotos%2Forudge%2F5602610471%2Flightbox%2F%23%2Fphotos%2Forudge%2F5602610471%2F','Road+Signs')" target="_blank"><img class="size-medium wp-image-3627" title="Road Signs" src="http://blog.ericlamb.net/wp-content/uploads/2011/04/routes-300x199.jpg" alt="Road Signs by orudge" width="300" height="199" /></a><p class="wp-caption-text">Road Signs by orudge</p></div>
<p>Recently though, I took on a project to build a sort of quick and dirty CMS with a couple unique requirements:</p>
<ol>
<li>It had to use the Zend Framework</li>
<li>URLs would be broken down into a /category/page/subpage scheme.</li>
</ol>
<p>This was the first time I&#8217;ve ever had a client demand a project use the Zend Framework. Pretty cool. But, this presented a problem because, as mentioned above, by default the Zend Framework has URL schemes based on the controller and action you&#8217;re looking to access like /controller/action/. This just wouldn&#8217;t work.</p>
<p>Since the clients URLs would mostly be based on user generated strings, what we were calling URL slugs, the default routing scheme just wouldn&#8217;t do. I say mostly because there were other areas of the project that would use the normal scheme for a couple modules. Either way, thankfully, using <a href="http://framework.zend.com/manual/1.11/en/zend.controller.router.html#zend.controller.router.routes.standard" onclick="return TrackClick('http%3A%2F%2Fframework.zend.com%2Fmanual%2F1.11%2Fen%2Fzend.controller.router.html%23zend.controller.router.routes.standard','Zend_Controller_Router_Route')" title="Zend_Controller_Router_Route" target="_blank">Zend_Controller_Router_Route</a> made this pretty much a snap (a little head bashing but not too much).</p>
<p>First though, a little background. Because of the above requirement from the client on URL schemes, I was thinking the best thing to do was to route all user generated URLs to to a single controller and handle the rest from there. I looked but there didn&#8217;t seem to be any easy way to route all URLs <em>except</em> the specific modules I wanted to exclude which meant I had to pull out the categories and iterate over them to create each route individually. (If anyone knows of a way to reverse the design and create a route for everything but certain strings let me know.)</p>
<p>To do this, in my bootstrap class I just created a new _init function like the below:</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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//bootstrap</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> _initRoutes<span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span>
<span style="color: #000;">&#123;</span>
	<span style="color: #000088;">$url_data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cat</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCategoryUrls</span><span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$frontController</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$router</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouter</span><span style="color: #000;">&#40;</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #22f;">foreach</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$url_data</span> <span style="color: #22f;">AS</span> <span style="color: #000088;">$url</span><span style="color: #000;">&#41;</span>
	<span style="color: #000;">&#123;</span>
&nbsp;
		<span style="color: #000088;">$route</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Controller_Router_Route <span style="color: #000;">&#40;</span>
			<span style="color: #000088;">$url</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'url_slug'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/*'</span><span style="color: #339933;">,</span>
			<span style="color: #990000;">array</span><span style="color: #000;">&#40;</span><span style="color: #0000ff;">'controller'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'pages'</span><span style="color: #339933;">,</span> 
			<span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'index'</span><span style="color: #000;">&#41;</span>
		<span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$router</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRoute</span><span style="color: #000;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #000;">&#91;</span><span style="color: #0000ff;">'url_slug'</span><span style="color: #000;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$route</span><span style="color: #000;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000;">&#125;</span> 
<span style="color: #000;">&#125;</span></pre></td></tr></table></div>

<p>In a nutshell, all the above is doing is looping over an array of category URL slugs and adding a custom route for each category that sends all requests to the Pages controller and the Index action. From there I parse the URL and proceed accordingly for the rest of the module. </p>
<p>For this example I&#8217;m doing a couple thing; using the Zend_Controller_Router_Route class and using wild cards (*). The Zend_Controller_Router_Route class takes two parameters, the first being the route and the second being an array of options (I&#8217;m only passing the controller and action but it&#8217;s possible to send others). For the route, and because it&#8217;s using the wildcard (*), I&#8217;m basically saying take any requests for the &#8220;url_slug&#8221; and anything after it and use the controller &#8220;Pages&#8221; and the &#8220;Index&#8221; action to handle everything. </p>
<p>After passing the Zend_Controller_Router_Route object to the $router, passing the unique name for the route as the first parameter, I was good to go. </p>
<p>That said, there&#8217;s a lot more that can be done with the custom routing stuff within the Zend Framework above what&#8217;s outlined above. There&#8217;s a pretty good article by <a href="http://www.wdvl.com/Authoring/PHP/Zend_Routes/Jason_Gilmore04282010.html" onclick="return TrackClick('http%3A%2F%2Fwww.wdvl.com%2FAuthoring%2FPHP%2FZend_Routes%2FJason_Gilmore04282010.html','Creating+Custom+Routes+with+the+Zend+Framework')" title="Creating Custom Routes with the Zend Framework" target="_blank">Jason Gilmore</a> that goes into some detail into how to create default URL parameters to make the URLs look even prettier. Definitely worth checking out. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ericlamb.net/2011/04/custom-routes-with-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.528 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-20 16:11:49 -->

