<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns: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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>techfounder</title>
	
	<link>http://www.techfounder.net</link>
	<description>Blog about web development and Internet entrepreneurship</description>
	<lastBuildDate>Mon, 06 Jul 2009 12:13:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Techfounder" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Writing specifications for web applications</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/KziEvpmajs0/</link>
		<comments>http://www.techfounder.net/2009/07/03/writing-specifications-for-web-applications/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 23:44:52 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[Lionite]]></category>
		<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=233</guid>
		<description><![CDATA[Specifications are an integral part of any web project (or any software project for that matter). Writing good specifications will improve the probability of success for a given project by a great deal.

Why spec?
Specifications encapsulate a project's goals, requirements, features and scope. This is very important for several reasons:
Understanding project requirements
Understanding what a project sets [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Specifications</strong> are an integral part of any web project (or any software project for that matter). Writing good specifications will improve the probability of success for a given project by a great deal.<br />
<span id="more-233"></span></p>
<h2>Why spec?</h2>
<p>Specifications encapsulate a project's <strong>goals</strong>, <strong>requirements</strong>, <strong>features</strong> and <strong>scope</strong>. This is very important for several reasons:</p>
<h3>Understanding project requirements</h3>
<p>Understanding what a project sets out to achieve might seem obvious, but in reality, when at least two people are involved - some difference in perception of the project goals and needs is inevitable. Putting in writing the goals and requirements goes a long way towards resolving such differences. </p>
<p>Writing specifications will often reveal requirements not thought of initially, as a result of detailing and thinking through the initial set of requirements. This is very important for determining project <strong>scope</strong>.</p>
<h3>Developing a project scope</h3>
<p>The <strong>scope</strong> of a project is probably the single most important attribute for determining project success. A well defined scope will determine the time-frame, costs and requirements with good precision. </p>
<p>In essence, a scope is the sum of a project features, requirements and deliverables or in other words - the sum of the work required for project completion.</p>
<p><em>Scope is the main element against which projects are priced at <a href="http://www.lionite.com" title="Lionite Internet Ventures">Lionite</a>. </em></p>
<p>The more complicated and/or innovative a project is, the more likely it is that features will change during the project lifetime (sometimes even drastically). </p>
<p>We can allow that to happen by adhering to scope instead of individual features. With good specifications it is much easier to avoid <a target="_blank" href="http://en.wikipedia.org/wiki/Scope_creep">scope-creep</a>.</p>
<h3>Estimating project time-frame and pricing</h3>
<p>Accurate time and cost estimates are important are as important to project success as anything else, and specifications are what it should be based on. </p>
<p>The better the written specifications are, the more accurate those estimates would be. </p>
<h3>Creating a workable reference for development and design</h3>
<p>Working with a good specifications document can do wonders for productivity and focus in the design and development stages. At the very least it can serve as a task list for project completion. </p>
<p>Well thought through description of features and relevant mockups can solve a lot of potential dillemas for both designers and developers and save a lot of time. </p>
<p>The specifications process itself should be used for ironing out as many issues as possible, helping the implementation phase to be as productive as possible.</p>
<h3>Having a standard to test against project delivery</h3>
<p>Specifications outline the agreement between parties on what constitutes a successful project delivery. Contracts, if relevant, will point to the specifications as the legally binding document for this purpose. </p>
<p>A good specifications document can resolve many potential disputes simply by stating clearly what should be delivered.</p>
<h2>How to create better specifications</h2>
<p>Creating good specifications entails some ground work, there's no around it. Keep in mind the effort you put in will pay itself back as the project progresses.</p>
<h3>Break everything down</h3>
<p>Decompose every requirement and feature to a list of small tasks. Add relevant detail that might affect completion time. The level of detail and scope of each task should be enough so that it could be accurately estimated in work hours (and not days, and certainly not weeks).</p>
<p><strong>Research</strong> what you are not sufficiently familiar with. This will greatly help avoid nasty surprises later, and will make your estimates that much more accurate.</p>
<h3>Be thorough</h3>
<p>Try to make sure there are no gaping holes in the specifications - are all requirements and features accounted for? are there any hidden prerequisites you might have over-looked? read everything twice and then give it to a colleague to read.</p>
<p>Don't forget to add more technical detail such as security concerns, coding standards, post-project technical support and supported browsers.</p>
<h3>Compose interactively with clients</h3>
<p>It is very important for the specifications to capture correctly the vision the client has for the project. Specifications writing can be used to correctly align client's expectations with your own. </p>
<p>Your interaction with the client can (and probably will) lead to more insights on project requirements and features. It is not at all uncommon for a project to change direction somewhat during specifications writing - and it is much better that it happens at that time than at mid-project.</p>
<h3>Be clear and concise</h3>
<p>Be clear and and use as much detail as necessary. Be concise, since overly descriptive texts are harder to consume and understand.</p>
<p>Don't skimp on rewording and reorganizing bulky / technical paragraphs and edit out unnecessary detail.</p>
<h3>Read more articles like this one</h3>
<p>Joel Spolsky on painless functional specifications - <a target="_blank" href="http://www.joelonsoftware.com/articles/fog0000000036.html">part 1</a>, <a href="http://www.joelonsoftware.com/articles/fog0000000035.html">part 2</a><br />
Allen Smith on <a target="_blank" href="http://www.mojofat.com/tutorial/">functional specifications</a><br />
Jason Fried of 37Signals on <a target="_blank" href="http://www.37signals.com/svn/archives/001050.php">avoiding functional specifications</a> (basically refuting everything I've written here. A good read for counter arguments.)</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=233" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=KziEvpmajs0:-oKXpU3MoHM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=KziEvpmajs0:-oKXpU3MoHM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=KziEvpmajs0:-oKXpU3MoHM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=KziEvpmajs0:-oKXpU3MoHM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=KziEvpmajs0:-oKXpU3MoHM:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/KziEvpmajs0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2009/07/03/writing-specifications-for-web-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2009/07/03/writing-specifications-for-web-applications/</feedburner:origLink></item>
		<item>
		<title>Multiple row operations in MySQL / PHP</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/dfMvuArNbXs/</link>
		<comments>http://www.techfounder.net/2009/05/14/multiple-row-operations-in-mysql-php/#comments</comments>
		<pubDate>Thu, 14 May 2009 01:43:43 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[insert]]></category>
		<category><![CDATA[multiple rows]]></category>
		<category><![CDATA[on duplicate key]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=229</guid>
		<description><![CDATA[Multiple row operations are in common use in a normalized application databases as one database entity is often linked to multiple sub-entities (for example a user and his tags). By row operations I'm referring to write queries, namely UPDATE and INSERT queries (DELETE is less interesting so I'll leave it out for now). 
Too often [...]]]></description>
			<content:encoded><![CDATA[<p>Multiple row operations are in common use in a normalized application databases as one database entity is often linked to multiple sub-entities (for example a user and his tags). By row operations I'm referring to write queries, namely UPDATE and INSERT queries (DELETE is less interesting so I'll leave it out for now). </p>
<p>Too often I've seen such queries ran in long loops one at a time, which is very bad for performance (as I will show here) and sometimes equally bad for integrity (if the process is interrupted). So what are the alternatives?<br />
<span id="more-229"></span></p>
<h2>Inserting multiple rows</h2>
<p>Insertion of multiple rows comes about often in batch jobs, database migrations and handling table relationships. A naive approach, via PHP, would be to loop over the data to be inserted, inserting one row at a time. Suppose the data is already properly filtered and quoted:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$data</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$row</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">      <span style="color: #0000ff;">$query</span> = <span style="color: #ff0000;">&quot;INSERT INTO `test_table` (user_id,content) VALUES (&quot;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">               . <span style="color: #0000ff;">$row</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'user_id'</span><span style="color: #66cc66;">&#93;</span> . <span style="color: #ff0000;">&quot;,&quot;</span> . <span style="color: #0000ff;">$row</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span> . <span style="color: #ff0000;">&quot;)&quot;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">      <a href="http://www.php.net/mysql_query"><span style="color: #000066;">mysql_query</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$query</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li></ol></pre>
<p>Depending on the amount of rows to be inserted, this can be a costly process. A better approach would be to concatenate the values into one insert query and then execute it:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0000ff;">$values</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$data</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$row</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">      <span style="color: #0000ff;">$values</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> =  <span style="color: #ff0000;">&quot;(&quot;</span> . <span style="color: #0000ff;">$row</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'user_id'</span><span style="color: #66cc66;">&#93;</span> . <span style="color: #ff0000;">&quot;,&quot;</span> . <span style="color: #0000ff;">$row</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span> . <span style="color: #ff0000;">&quot;)&quot;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/empty"><span style="color: #000066;">empty</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$values</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">     <span style="color: #0000ff;">$query</span> = <span style="color: #ff0000;">&quot;INSERT INTO `test_table` (user_id,content) VALUES &quot;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">               . <a href="http://www.php.net/implode"><span style="color: #000066;">implode</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">','</span>,<span style="color: #0000ff;">$values</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">     <a href="http://www.php.net/mysql_query"><span style="color: #000066;">mysql_query</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$query</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li></ol></pre>
<p>What's the difference? lets see some benchmarks:<br />
<img src="http://www.techfounder.net/wp-content/uploads/2009/05/time.png" alt="time" title="time" width="485" height="205"  /><br />
A single query completes <b>much</b> faster than looping through multiple queries. At 2560 rows inserted, it took the loop ~36 seconds to complete, yet the single query took just 0.14 seconds.</p>
<p>Memory consumption shows a reverse trend however:<br />
<img src="http://www.techfounder.net/wp-content/uploads/2009/05/memory.png" alt="memory" title="memory" width="481" /><br />
Since the values are concatenated to create the single query, it consumes more and more memory with more rows as it needs to hold a larger query string. At 2560 rows inserted, the single query approach consumed ~800kb in memory, while the loop consumed just ~60kb.</p>
<p>Since memory is much cheaper than CPU cycles and database connections, I'd usually opt for the single query approach. It's important though to be aware of the implications.</p>
<h2>Inserting / Updating (multiple) values</h2>
<p>Another use-case of multiple row operations is when we want to insert several rows that might exist already, and in case they exist we want to update existing values instead. Of course, we could check first which rows exist, update the ones that do and insert the ones that don't - for a total of at least three separate queries. </p>
<p>The update query is the major problem here - there is no way to update multiple rows with different values using one query (and it doesn't make much sense in most cases). However in this case it does make sense to do so, and fortunately MySQL provides a way to do just that, using <a href="http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html" target="_blank">INSERT ... ON DUPLICATE KEY UPDATE</a>.</p>
<p>The KEY in this statement should be a unique key in the table you are inserting to (otherwise duplicates would be allowed and this operation would be moot). The syntax of this statement allows to pick which columns are updated in the case of matching rows. For example, suppose I'm adding translations for content pages. I have the following table schema:</p>
<pre class="sql">&nbsp;
pages
 - id
 - content
 - ...
&nbsp;
pages_translations
 - page_id
 - lang_id
 - content
&nbsp;</pre>
<p>The pages_translations table has a primary (unique) key on ( page_id , lang_id ). When adding / updating a translation, the query would look something like:</p>
<pre class="sql"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`pages_translations`</span> <span style="color: #66cc66;">&#40;</span>page_id,lang_id,content<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #ff0000;">'the brown fox ...'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">ON</span> DUPLICATE <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">UPDATE</span> content=<span style="color: #993333; font-weight: bold;">VALUES</span><span style="color: #66cc66;">&#40;</span>content<span style="color: #66cc66;">&#41;</span>
&nbsp;</pre>
<p>This will create a translation if one does not exist and update the content field if it does exist. We can combine this statement with the previous approach for multiple insertion to insert / update multiple rows with one statement.</p>
<h2>Inserting / Updating with multiple tables</h2>
<p>There are some cases where we would like to use data in one or several tables to update / insert into another table. </p>
<p>With insertion the <a href="http://dev.mysql.com/doc/refman/5.1/en/insert-select.html" target="_blank">syntax is relatively straightforward</a> - replace the VALUES part of the statement with a SELECT statement. </p>
<pre class="sql"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`my_table`</span> <span style="color: #66cc66;">&#40;</span>col1,col2,col3<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> col4,col5,col6
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`another_table`</span></pre>
<p>The ON DUPLICATE KEY condition can be used with this statement as well.</p>
<p>Updating rows cross-tables is done with a JOIN statement (of the less declarative type).</p>
<pre class="sql"><span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #ff0000;">`my_table`</span>,<span style="color: #ff0000;">`other_table`</span>
   <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #ff0000;">`my_table`</span>.col1 = <span style="color: #ff0000;">`other_table`</span>.col2
<span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #ff0000;">`my_table`</span>.parent_id = <span style="color: #ff0000;">`other_table`</span>.id</pre>
<p>It's important to try the INSERT / UPDATE select statements separately to determine how many rows they will select and how fast will they complete. INSERT / UPDATE operations are relatively costly and can be a severe bottleneck for the database if not managed correctly.</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=229" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=dfMvuArNbXs:FAx3P7rI56g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=dfMvuArNbXs:FAx3P7rI56g:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=dfMvuArNbXs:FAx3P7rI56g:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=dfMvuArNbXs:FAx3P7rI56g:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=dfMvuArNbXs:FAx3P7rI56g:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/dfMvuArNbXs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2009/05/14/multiple-row-operations-in-mysql-php/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2009/05/14/multiple-row-operations-in-mysql-php/</feedburner:origLink></item>
		<item>
		<title>Finding your web business model</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/Dd0XP6x8vdw/</link>
		<comments>http://www.techfounder.net/2009/05/06/finding-your-web-business-model/#comments</comments>
		<pubDate>Tue, 05 May 2009 23:28:26 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[Business Development]]></category>
		<category><![CDATA[Lionite]]></category>
		<category><![CDATA[advertising]]></category>
		<category><![CDATA[business model]]></category>
		<category><![CDATA[experiments]]></category>
		<category><![CDATA[startup]]></category>
		<category><![CDATA[subscription]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=236</guid>
		<description><![CDATA[The web as a commercial venue has changed and evolved much in the relatively short time since its inception. As the medium and technology evolved, more and more "real-world" business models became viable for web products. 
Despite this, the application of those business models in the web arena is still very much experimental, and it's [...]]]></description>
			<content:encoded><![CDATA[<p>The web as a commercial venue has changed and evolved much in the relatively short time since its inception. As the medium and technology evolved, more and more "real-world" business models became viable for web products. </p>
<p>Despite this, the application of those business models in the web arena is still very much experimental, and it's often hard for web businesses to find and implement a model that works well for them.<br />
<span id="more-236"></span></p>
<h2>Got ads?</h2>
<p>The most basic misconception about web business models is that you can never go wrong choosing an advertising-based model. If it was really that easy, then everybody would be making mad cash - however, advertising based revenue is actually hard to come by. </p>
<p>In fact, those who can actually make it stick are few and far between (Mike Speiser <a href="http://laserlike.com/2008/09/14/the-advertising-equivalence-principle/" target="_blank">shows the numbers don't lie</a>). The amount of traffic you need to generate in order to make substantial revenue from online advertising is out of reach for the vast majority of websites.</p>
<p>So when is an advertising model appropriate? </p>
<ul>
<li>When generating traffic is the <b>main purpose</b> of your web service. Such sites include all flavors of traditional content sites, social networks, user-generated content sites and the like.</li>
<li>When your service has the ability to deliver <b>targeted advertising</b>. Targeting advertising at user activity, search criteria and the like, greatly increase the relevancy of ads and thus conversion rates. A <a href="http://www.google.com" target="_blank" title="Google">little-known company</a> has made targeted advertising <a href="http://investor.google.com/fin_data.html" target="_blank" title="Google financial data">its main business</a> to devastating effect.</li>
<li>Advertising is incorporated as a part of a hybrid model, to subsidize free parts of the service (see below for more details).</li>
</ul>
<p>The important attribute here is that advertising must target a large enough audience with sufficient relevancy in order to generate significant revenue. </p>
<h2>Subscription is king</h2>
<p>Subscription business models are nothing new but have been gaining popularity on the web, especially with the proliferation of on-demand online services in which subscription payments often make the most sense.</p>
<p>A subscription-based model is often appropriate when the service / content offered is unique and hard to find elsewhere. For site visitors to shell out even a few dollars, they need to be convinced that they are getting something they can't get elsewhere (since much of the web is available for free). This is doubly true since the process of handing out payments details online is often a barrier by itself.</p>
<p>Whether it's entertainment or productivity, when the value to users is higher than or equal to the monetary cost subscription becomes a very viable model. Niche sites and web services often fall in this category when they provide something of value.</p>
<p>I'd note here that by subscription model I don't necessarily mean just recurring annual subscriptions - there are also milestone-based subscriptions (pay-as-you-go) and feature-based subscriptions (pay-per-feature). Those three types can be mixed together to create many different hybrids, with the common denominator being the "subscribed user" - a person willing to spend money to use the service.</p>
<h2>The freemium model</h2>
<p>Freemium is a trendy new name for a familiar model - offer basic or limited services for free, and charge for advanced (premium) features. <a href="http://www.avc.com/a_vc/2006/03/my_favorite_bus.html" target="_blank">The freemium model</a> is often a derivative of the subscription model, with the basic subscription plan as the free part of it. </p>
<p>Using a freemium model can be very useful for businesses who are counting on long-term users instead of one-time purchases. By getting limited services for free, a user can have a taste of what the web service has to offer thus lowering the barrier of entry. The balance of free to premium is important in creating the right incentive for paying for the premium services (example - <a href="http://www.basecamphq.com/signup" target="_blank">basecamp</a>). </p>
<p>One common application of the freemium model is combining the subscription and advertising models, by offering free services that display ads and premium services that are ad-free - this basically allows the site user to decide how he will support the service.</p>
<p>When we are conducting business development with clients I Personally lean mostly to subscription based freemium model, as </p>
<h2>The brokers</h2>
<p>Brokers are services that bring together buyers and sellers thus creating a marketplace. Revenue is generated by charging usage of the marketplace in a variety of ways:</p>
<ul>
<li>Sellers can be charged for being listed by the broker (one time / per listing)</li>
<li>Buyers can be charged for gaining access to the listing of sellers</li>
<li>Fee / commission on successful transactions</li>
</ul>
<p>The best known example of the broker model is <a href="http://www.ebay.com">Ebay</a>, a giant marketplace that succeeds on the strength of its reputation system and internal policing. A couple of good examples for creative application of the broker model are threadless and crowdspring (which I described in a <a href="http://www.techfounder.net/2008/08/23/a-web-20-business-model-can-work-and-work-well/">previous post on web business models</a>).</p>
<h2>The partnership, the exit</h2>
<p>Partnerships can be the basis of viable business model in certain circumstances - such as affiliates and sponsorships, or can be another part of the whole for others. It is often used as a hybrid with other models (such as advertising or subscription) being the driving force behind revenue.</p>
<p>An extreme case of this model is the outright takeover of the business by another company, often called "<a href="http://www.startupnation.com/articles/920/1/AT_WhatIsYourExitStrategy.asp" target="_blank">an exit</a>". Though some businesses set out with this strategy in mind, its very unpredictable nature makes it very risky without an adequate backup model. I call this strategy the "no-model" model, with businesses basically saying that they'll figure out as they go along, hoping that some giant company will swoop in and end all their problems.</p>
<h2>Picking the right one</h2>
<p>Deciding on a web business model can be tough for early stage start-ups and traditional offline businesses transitioning to the web. Each model has its pros and cons and the fear of making a mistake can be paralyzing. Sometimes the perfect business model is very obvious but more often than not it's a journey of self discovery for the business.</p>
<p>When <a href="http://www.lionite.com" target="_blank" title="Lionite Internet Ventures">we</a> engage in business development with our clients, we usually ask them the following questions:</p>
<ul>
<li>What is your target audience?</li>
<li>How much would you pay for your service?</li>
<li>Who are your competitors? What is their business model?</li>
<li>When (or how fast) do you expect web revenue to cover operating expenses?</li>
</ul>
<p>Those are mostly introductory questions, aimed at helping the business orient itself on what it needs to know to determine its business model. </p>
<h2>Analyze, improve, rinse, repeat</h2>
<p>Choosing a business model is only the beginning. Constant collection and analysis of related data - such as conversion and churn rates,  usage data and statistics - is essential for tweaking and evolving the business model and increasing its chances of success. The process of testing how much customers are willing to pay for services is sometimes called <a href="http://venturehacks.com/articles/pricing" target="_blank">bounding-box pricing</a>.</p>
<p>There are no strict rules for choosing a business model, so don't be afraid to experiment and look for business opportunities in unexpected places. You never know when or where your big break will happen, but if you believe in your product and your team your business model will reveal itself eventually - be prepared for it when it happens.</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=236" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=Dd0XP6x8vdw:G-EsB2TGFUs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=Dd0XP6x8vdw:G-EsB2TGFUs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=Dd0XP6x8vdw:G-EsB2TGFUs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=Dd0XP6x8vdw:G-EsB2TGFUs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=Dd0XP6x8vdw:G-EsB2TGFUs:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/Dd0XP6x8vdw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2009/05/06/finding-your-web-business-model/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2009/05/06/finding-your-web-business-model/</feedburner:origLink></item>
		<item>
		<title>Lionite relaunched! time to kick back… and work some more</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/AzIhCRW95Ho/</link>
		<comments>http://www.techfounder.net/2009/04/30/lionite-relaunched-time-to-kick-back-and-work-some-more/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 23:53:06 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=242</guid>
		<description><![CDATA[For a long time, we've been feverishly developing beautiful sites for others while our own site was left to rot in mediocrity for lack of time. Now, finally, we've taken the time to properly redesign and relaunch our portfolio website, at http://www.lionite.com:


We went for an illustration-style design. Those characters are actually us (the Lionite team), [...]]]></description>
			<content:encoded><![CDATA[<p>For a long time, we've been feverishly developing beautiful sites for others while our own site was left to rot in mediocrity for lack of time. Now, finally, we've taken the time to properly redesign and relaunch our portfolio website, at <a title="Lionite Internet Ventures" href="http://www.lionite.com" target="_blank">http://www.lionite.com</a>:</p>
<p><img class="alignnone size-full wp-image-258" title="lionite_new3" src="http://www.techfounder.net/wp-content/uploads/2009/04/lionite_new3.jpg" alt="lionite_new3" width="510" height="244" /><br />
<span id="more-242"></span><br />
We went for an illustration-style design. Those characters are actually us (the Lionite team), building the site <img src='http://www.techfounder.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I am standing on the ladder to the right, in case you wondered.</p>
<p>The content on the site is still going through some incremental upgrades, but I really liked our designer's rendition of my idea for a development iteration:<img class="alignnone size-full wp-image-259" title="lionite_method1" src="http://www.techfounder.net/wp-content/uploads/2009/04/lionite_method1.jpg" alt="lionite_method1" width="510" height="144" /></p>
<p>And how it integrated nicely into the portfolio pieces (inserting shameless plug for our startup):</p>
<p><a href="http://www.techfounder.net/wp-content/uploads/2009/04/lionite_portfolio.jpg"><img class="alignnone size-full wp-image-250" style="float:none;" title="lionite_portfolio" src="http://www.techfounder.net/wp-content/uploads/2009/04/lionite_portfolio.jpg" alt="" /></a></p>
<p>Those icons are on or off depending on our roles for each project.</p>
<p>We are very pleased with the final result and we the feedback has been very positive so far. Now begins the real challenge - promoting the brand and getting leads through the site. Time to get back to work!</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=242" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=AzIhCRW95Ho:oF1mvSvB8kU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=AzIhCRW95Ho:oF1mvSvB8kU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=AzIhCRW95Ho:oF1mvSvB8kU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=AzIhCRW95Ho:oF1mvSvB8kU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=AzIhCRW95Ho:oF1mvSvB8kU:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/AzIhCRW95Ho" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2009/04/30/lionite-relaunched-time-to-kick-back-and-work-some-more/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2009/04/30/lionite-relaunched-time-to-kick-back-and-work-some-more/</feedburner:origLink></item>
		<item>
		<title>Conveying value to clients</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/DkH_B5YbEZE/</link>
		<comments>http://www.techfounder.net/2009/04/05/conveying-value-to-clients/#comments</comments>
		<pubDate>Sun, 05 Apr 2009 03:31:37 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[Business Development]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[techfounder]]></category>
		<category><![CDATA[price proposal]]></category>
		<category><![CDATA[web project clients]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=151</guid>
		<description><![CDATA[Preface: This article was written mostly half a year ago, as I was wrapping up an intense period of freelancing and sub-contracting. It is less relevant for me now, as I'm now an equal partner in a small web firm and my freelancing days are beyond me - however, I thought it might be a [...]]]></description>
			<content:encoded><![CDATA[<p>Preface: This article was written mostly half a year ago, as I was wrapping up an intense period of freelancing and sub-contracting. It is less relevant for me now, as I'm now an equal partner in a <a title="Lionite Internet Services" href="http://www.lionite.com" target="_blank">small web firm</a> and my freelancing days are beyond me - however, I thought it might be a good read.</p>
<p><span id="more-151"></span></p>
<h2>How much are you worth</h2>
<p>As a freelancer and sub-contractor, one of the basic skills I had to develop is conveying value to prospective clients. In order to earn the rates I want to charge, it's important to make the client understand the value he is getting in return.</p>
<p>Clients seeking freelancers are often looking for cheaper rates, as the thinking goes that companies inherently charge more - companies have additional costs that freelancers do not, and those costs are reflected in their rates.</p>
<p>While looking for cheaper rates, clients still expect quality - and those two properties have a very tangible relationship. You can assume higher rates reflect greater quality - however, in software development, quality is an attribute that is hard to explain to non-technical people, and as in every other occupation, higher rates don't necessarily mean higher quality.</p>
<p>My goal when communicating with a prospective client is to convey to him what is the value that I bring to the table. While admittedly my rates are not cheap - I believe they are more than fair, and the value I can give greatly exceeds the monetary compensation I demand for it.</p>
<p>So how can I convince a client that I'm worth what I ask for?</p>
<h2>Talking about quality in software development</h2>
<p>The following are metrics that are widely accepted as proponents of software quality:</p>
<ul>
<li>Maintainability - How easy is it to debug and maintain the source code? How is it to make small changes?<br />
The cost of maintaining the product over any stretch of time is highly dependent on this. Also, larger development projects will bog down during active development if they are not maintainable.</li>
<li>Extendability - How easy is it to add functionality and features to the product? This affects the cost of future development, cost that may be larger than the original investment.</li>
<li>Security - How secure is the product against known and unknown exploits in its domain? This concerns mostly products with online accessibility, which places web products at the highest risk spectrum.</li>
<li>Domain relevance - How well does the product actually answers the problems it sets to solve? this is a metric that is hard to measure without real users testing the product. However, having plenty of experience in this area can definitely reduce the margin of error.</li>
</ul>
<p>And another metric that is not software-development specific:</p>
<ul>
<li>Professionalism - How much respect does a service provider has for his line of work? how much respect does he have for his clients and how much does he put into his communications with them? how good is he with meeting time schedules and price estimates?</li>
</ul>
<p>There are many ways in which I try to convey the value I can give in each of those areas -</p>
<ul>
<li>By presenting my best work in <a title="Xplace" href="http://www.xplace.com/ShowCompany.xpl?co=7628">online</a> <a href="http://www.bizreef.co.il/biz/Lionite">profiles</a> with a short summary of the what I reviewed above. (Warning - links are in Hebrew <img src='http://www.techfounder.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</li>
<li>By writing in my <a title="My blog! you are here" href="http://www.techfounder.net">blog</a> about issues relevant to those qualities.</li>
<li>By actively participating in <a title="DevNet PHP forums" href="http://forums.devnetwork.net/memberlist.php?mode=viewprofile&amp;u=36058">forums</a> and other software development <a title="Stackoverflow" href="http://stackoverflow.com/users/10585/eran-galperin">communities</a>.</li>
<li>By always trying to be transparent and professional in any communication with clients.</li>
</ul>
<p>The fact that I perform those activities because I enjoy and learn from them is to my advantage. <img src='http://www.techfounder.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Those activities are mostly behind the scenes though, cause the next most important step is:</p>
<h2>Striving for a face-to-face meeting</h2>
<p>My number one goal is to meet clients face-to-face. By putting a face behind the CV and answering any  questions in a professional manner, I increase the chances of a closing a deal tenfold.</p>
<p>I know many freelance developers have a reluctance to meet face-to-face, and are generally shy in such meetings. For the most part I embrace it - I strongly believe that after such a meeting the client will know exactly what value I stand for, and then it will only come down to costs versus value considerations.</p>
<p>Another equally important aspect of the face-to-face meeting is to understand in greater detail the scope and features of the project. Often, a second meeting for specifications only is required. I will write about the specification process in a future article, hopefully.</p>
<h2>Creating a transparent and fair cost and scope proposal</h2>
<p>When creating the actual price proposal it's important to keep two things in mind:</p>
<ul>
<li>Be clear on what's included in the proposal</li>
<li>Make it obvious how much every part costs separately</li>
</ul>
<p>Being clear on what's included in the proposal is a no-brainer. It will prevent future misunderstandings and points of contention. To a large degree, this is also influenced by the level of specifications document attached to the proposal (you do have one, don't you?).</p>
<p>Making it obvious how much every part costs is an effective way to translate to a client how much effort will it take to develop specific features. This allows a client to make value considerations - how much a feature is worth to the project versus how much it will cost to develop it, and often allows for compromises that can take a price proposal from the "out of range" zone to the "let's do business" zone.</p>
<p>Allow the client to make his own decisions regarding what features to keep or leave out, but provide your opinion as well. We, as web professionals, have a responsibility of educating our clients with our knowledge and experience in the field. Don't be afraid to influence the client with what you think is best for the project.</p>
<h2>Stand behind your pricing</h2>
<p>This might be difficult advice in those times of economic strife, however I strongly recommend standing firm beyond your price proposals if you believe them to be fair and thought out. If you represent with conviction that the price proposal stands for your worth, it increases your integrity in the eyes of the client.</p>
<p>Never leave money you believe you are worth on the table. There are other ways to come to terms that all sides can live with, such as trimming down on features and scope or converting some of the cost into shares in the project.</p>
<p><strong>Flashback: </strong></p>
<p>I remember that when I wrote this piece I had just submitted a price proposal for a freelance project at the sum of around 4,000$US. I was pretty sure I had conveyed my value perfectly to the client, though he had argued that the price is unacceptable for him. He wanted to close it at 2,500$, which is a pretty steep cut.</p>
<p>I was caught in a serious dillemma - I was out of the market for a couple of months, living off previous projects income, and it was the height of the financial crisis. Should I take the hit and take the project anyway or stick with my pricing?</p>
<p>I decided to hold firm to my pricing. The client went off to request more price proposals from other developers (with my specifications document - which at the time I was not charging for), but continued to contact me in 2-3 weeks interval, asking whether I'd be willing to come closer to his terms.</p>
<p>In the mean time I started my own <a href="http://www.lionite.com" target="_blank">web company</a> with two other extremely talented partners, and we went on to close several major projects that make that 4000$ seem a bit disproportional right now. I was recently contacted for a last time by that client, and I was happy to respond that I'm no longer available for his project.</p>
<p>My own moral of this story is that if you follow through with your beliefs and represent your value well, you will eventually get through to the right clients. Clients that refuse to recognise that they need to pay for the quality they want to recieve, are clients that I rather not work with.</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=151" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=DkH_B5YbEZE:HKt1unO2o2s:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=DkH_B5YbEZE:HKt1unO2o2s:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=DkH_B5YbEZE:HKt1unO2o2s:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=DkH_B5YbEZE:HKt1unO2o2s:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=DkH_B5YbEZE:HKt1unO2o2s:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/DkH_B5YbEZE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2009/04/05/conveying-value-to-clients/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2009/04/05/conveying-value-to-clients/</feedburner:origLink></item>
		<item>
		<title>Selecting closest values in MySQL</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/xSJ8m53Rwas/</link>
		<comments>http://www.techfounder.net/2009/02/02/selecting-closest-values-in-mysql/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 03:12:54 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[range select]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=213</guid>
		<description><![CDATA[Sometimes the need arises to select several values in the vicinity of a certain value, preferably ordered by proximity. The values might be dates, zip-codes or any other meaningfully ordered values that can be represented as numerical values. How can we pull this off in MySQL?

We can't use a simple ORDER BY, since we want [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes the need arises to select several values in the vicinity of a certain value, preferably ordered by proximity. The values might be dates, zip-codes or any other meaningfully ordered values that can be represented as numerical values. How can we pull this off in MySQL?<br />
<span id="more-213"></span><br />
We can't use a simple ORDER BY, since we want values both larger and smaller than our selected value. We can however order by an aggregate function that calculates the distance from our selected value.</p>
<p>Suppose we want to find the 6 closest numbers to the number 2500 (including) from a numbers table:</p>
<pre class="sql"><span style="color: #993333; font-weight: bold;">SELECT</span> number, ABS<span style="color: #66cc66;">&#40;</span> number - <span style="color: #cc66cc;">2500</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> distance
<span style="color: #993333; font-weight: bold;">FROM</span> numbers
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> distance
<span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">6</span></pre>
<p>This returns:</p>
<table id="table_results" class="data" border="0">
<thead>
<tr>
<th>number</th>
<th>distance</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2502</td>
<td>2</td>
</tr>
<tr class="even">
<td>2494</td>
<td>6</td>
</tr>
<tr class="odd">
<td >2508</td>
<td>8</td>
</tr>
<tr class="even">
<td >2489</td>
<td>11</td>
</tr>
<tr class="odd">
<td >2513</td>
<td>13</td>
</tr>
<tr class="even">
<td >2487</td>
<td>13</td>
</tr>
</tbody>
</table>
<blockquote><p>(6 total, Query took 2.2792 sec)</p></blockquote>
<p>This works nicely, and is actually relatively performant if the number column is indexed. Despite having to run a full table scan in order to calculate the distance for every number in the table, running this on a ~2 million row table completes in just over 2 seconds.</p>
<p>This kind of performance would be quite enough for smaller tables, but often in real time applications we would like faster response times than 2 seconds for completing a query.</p>
<p>Since we know exactly what we need, we can help MySQL by limiting the range of numbers it has to calculate the distance for. Since we want the 6 closest numbers, we can be sure they'll be at most in a range of 6 numbers lower and 6 numbers higher than our selected value.</p>
<p>If we can do that, then the calculation would run for only 13 numbers, hopefully leading to much improved performance. Selecting those numbers can be done using a union on a couple of SELECT statements:</p>
<pre class="sql"><span style="color: #66cc66;">&#40;</span>
   <span style="color: #993333; font-weight: bold;">SELECT</span> number
   <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`numbers`</span>
   <span style="color: #993333; font-weight: bold;">WHERE</span> number &amp;gt;=<span style="color: #cc66cc;">2500</span>
   <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> number
   <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">7</span>
<span style="color: #66cc66;">&#41;</span> UNION <span style="color: #993333; font-weight: bold;">ALL</span> <span style="color: #66cc66;">&#40;</span>
   <span style="color: #993333; font-weight: bold;">SELECT</span> number
   <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`numbers`</span>
   <span style="color: #993333; font-weight: bold;">WHERE</span> number &amp;lt;<span style="color: #cc66cc;">2500</span>
   <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> number <span style="color: #993333; font-weight: bold;">DESC</span>
   <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">6</span>
<span style="color: #66cc66;">&#41;</span></pre>
<p>Notice the first one includes the actual value (in case it exists) and hence has one more value to select in its limit clause.</p>
<p>Combining this with our previous successful attempt produces the following ungainly query:</p>
<pre class="sql"><span style="color: #993333; font-weight: bold;">SELECT</span> number, ABS<span style="color: #66cc66;">&#40;</span> number - <span style="color: #cc66cc;">2500</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> distance <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#40;</span>
	<span style="color: #66cc66;">&#40;</span>
		<span style="color: #993333; font-weight: bold;">SELECT</span> number
		<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`numbers`</span>
		<span style="color: #993333; font-weight: bold;">WHERE</span> number &amp;gt;=<span style="color: #cc66cc;">2500</span>
		<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> number
		<span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">6</span>
	<span style="color: #66cc66;">&#41;</span> UNION <span style="color: #993333; font-weight: bold;">ALL</span> <span style="color: #66cc66;">&#40;</span>
		<span style="color: #993333; font-weight: bold;">SELECT</span> number
		<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`numbers`</span>
		<span style="color: #993333; font-weight: bold;">WHERE</span> number &amp;lt;<span style="color: #cc66cc;">2500</span>
		<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> number <span style="color: #993333; font-weight: bold;">DESC</span>
		<span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">6</span>
	<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> n
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> distance
<span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">6</span></pre>
<p>It does return the same results:</p>
<table id="table_results" class="data" border="0">
<thead>
<tr>
<th class="condition">number</th>
<th>distance</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="condition nowrap" align="right">2502</td>
<td class="nowrap" align="right">2</td>
</tr>
<tr class="even">
<td class="condition nowrap" align="right">2494</td>
<td class="condition nowrap" align="right">6</td>
</tr>
<tr class="odd">
<td class="condition nowrap" align="right">2508</td>
<td class="condition nowrap" align="right">8</td>
</tr>
<tr class="even">
<td class="condition nowrap" align="right">2489</td>
<td class="condition nowrap" align="right">11</td>
</tr>
<tr class="odd">
<td class="condition nowrap" align="right">2513</td>
<td class="condition nowrap" align="right">13</td>
</tr>
<tr class="even">
<td class="condition nowrap" align="right">2487</td>
<td class="condition nowrap" align="right">13</td>
</tr>
</tbody>
</table>
<p>Is much more performant:</p>
<blockquote><p>(6 total, Query took 0.0011 sec)</p></blockquote>
<p>And there you have it.</p>
<p>A couple of notes:<br />
- All queries were ran with SQL_NO_CACHE at least 5 times to ensure the timings were indicative of the performance.<br />
- The queries were ran against a ~2 million table filled with randomly generated values.<br />
- An index was created on the number column.</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=213" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=xSJ8m53Rwas:AnShrybox38:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=xSJ8m53Rwas:AnShrybox38:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=xSJ8m53Rwas:AnShrybox38:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=xSJ8m53Rwas:AnShrybox38:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=xSJ8m53Rwas:AnShrybox38:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/xSJ8m53Rwas" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2009/02/02/selecting-closest-values-in-mysql/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2009/02/02/selecting-closest-values-in-mysql/</feedburner:origLink></item>
		<item>
		<title>Zend Framework certification</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/dKzXc27gxZY/</link>
		<comments>http://www.techfounder.net/2008/12/30/zend-framework-certification/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 17:59:07 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[techfounder]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=195</guid>
		<description><![CDATA[Today I took and passed the Zend Framework certification exam. A possible project involving Zend might be materializing in the near future, and this was a requirement from one of my contractors (OpenIT). Being that they offered to sponsor the cost, I had no reason not take it.
As I found no concrete online information on [...]]]></description>
			<content:encoded><![CDATA[<p>Today I took and passed the <a href="http://www.zend.com/en/services/certification/framework/">Zend Framework certification exam</a>. A possible project involving Zend might be materializing in the near future, and this was a requirement from one of my contractors (<a href="http://www.openit.co.il/">OpenIT</a>). Being that they offered to sponsor the <a href="http://www.zend.com/en/store/php-certification/zend-framework-certification-exam-voucher">cost</a>, I had no reason not take it.</p>
<p>As I found no concrete online information on the test (and the <a href="http://downloads.zend.com/framework/generic/ZFC_Study_Guide_v1.pdf">guide link</a> from Zend doesn't work), I might as well elaborate a little for the benefit of future test takers reading this blog -<br />
<span id="more-195"></span><br />
The test is 1.5 hours long and composed of 75 questions. Most questions are multiple choice with the rest being open-ended (usually requiring to enter what you believe will the be the result input from several manipulations). The scope of the test is pretty encompassing, touching some modules that I wouldn't normally use (or even imagine a <a href="http://framework.zend.com/manual/en/zend.memory.html">possible use scenario for</a>), but if you have enough experience of the core features (MVC, Db, Cache, Filter/Validation, Localization / Internationalization and Security) and coding standards - you should do just fine.</p>
<p>The one thing to watch out for is the relatively high percentage of trick questions - which actually made the test somewhat harder than I'd anticipated (after you hit several trick questions in a row, you start being suspicious of every question). Some questions didn't even have an absolutely right answer, but sort of the answer of least incorrectness.</p>
<p>Thankfully, 1.5 hours is plenty long for delibrating some of those more ambigious questions - I had finished my first run in about 35 minutes and rechecked everything in 10 more minutes - leaving me 45 minutes to spare.</p>
<p>I do have some more respect for people holding the certification now (regarding knowledge and experience), though I'm not sure what regard does it hold in the industry (this is the first time I've encountered someone asking for it - and the client is Zend itself, so it's not surprising). If anyone has had previous experience with ZF certification qualification requirements, I would love to hear it.</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=195" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=dKzXc27gxZY:v-7-4ELJTl0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=dKzXc27gxZY:v-7-4ELJTl0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=dKzXc27gxZY:v-7-4ELJTl0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=dKzXc27gxZY:v-7-4ELJTl0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=dKzXc27gxZY:v-7-4ELJTl0:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/dKzXc27gxZY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2008/12/30/zend-framework-certification/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2008/12/30/zend-framework-certification/</feedburner:origLink></item>
		<item>
		<title>If you like t-shirts, check this out</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/H-T_MvuPh8I/</link>
		<comments>http://www.techfounder.net/2008/12/11/if-you-like-t-shirts-check-this-out/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 13:07:30 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[Interesting]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=184</guid>
		<description><![CDATA[My good friend and Octabox co-founder, Tal Zubalsky, is a graphic designer by trade. He is also an avid t-shirts fan and therefor a threadless fan (who isn't?   ).
He has recently decided to have a go at a t-shirt design himself, and came up with this brilliant concept which I think is pretty [...]]]></description>
			<content:encoded><![CDATA[<p>My good friend and <a target="_blank" title="Octabox Web Platform" href="http://www.octabox.com">Octabox</a> co-founder, Tal Zubalsky, is a graphic designer by trade. He is also an avid t-shirts fan and therefor a <a title="Threadless" href="http://www.threadless.com/" target="_blank">threadless</a> fan (who isn't? <img src='http://www.techfounder.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</p>
<p>He has recently decided to have a go at a t-shirt design himself, and came up with <a title="Threadless design - The Texas Gardener" href="http://www.threadless.com/submission/188098/The_Texas_Gardener" target="_blank">this brilliant concept</a> which I think is pretty awesome. If you like t-shirts and have a threadless account, please take the time to have a look and vote for it (I'd really like to see it printed <img src='http://www.techfounder.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ).</p>
<p><a title="Threadless design - The Texas Gardener" href="http://www.threadless.com/submission/188098/The_Texas_Gardener" target="_blank"><img style="float:none; display:block; margin:auto;" src="http://www.techfounder.net/wp-content/uploads/2008/12/texas_gardener.jpg" alt="Threadless design - Texas Gardener" /></a></p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=184" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=H-T_MvuPh8I:j9oyzNGGFIE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=H-T_MvuPh8I:j9oyzNGGFIE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=H-T_MvuPh8I:j9oyzNGGFIE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=H-T_MvuPh8I:j9oyzNGGFIE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=H-T_MvuPh8I:j9oyzNGGFIE:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/H-T_MvuPh8I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2008/12/11/if-you-like-t-shirts-check-this-out/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2008/12/11/if-you-like-t-shirts-check-this-out/</feedburner:origLink></item>
		<item>
		<title>OO PHP templating</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/QuNo8Y6rSIs/</link>
		<comments>http://www.techfounder.net/2008/11/18/oo-php-templating/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 04:00:05 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[templating]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=135</guid>
		<description><![CDATA[Templating is a common technique for separation of concerns in applications - separating presentational logic from domain (or business) logic. This kind of separation promotes higher maintainability and a better chance to reuse presentational code (by encapsulating it in templates), the kind of traits we would all love to have in our code base.

PHP as [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Wikipedia - templating" href="http://en.wikipedia.org/wiki/Web_template_system" target="_blank">Templating</a> is a common technique for <a title="Wikipedia - separation of concerns" href="http://en.wikipedia.org/wiki/Separation_of_concerns" target="_blank">separation of concerns</a> in applications - separating presentational logic from domain (or business) logic. This kind of separation promotes higher maintainability and a better chance to reuse presentational code (by encapsulating it in templates), the kind of traits we would all love to have in our code base.<br />
<span id="more-135"></span><br />
PHP as a language can be considered a templating system, as in its root it was meant to modify HTML pages dynamically. The need for more structured templating systems arose as PHP applications have grown more and more complex, giving birth to much more specialized and focused solutions.</p>
<h2>Search-and-replace Vs. Include</h2>
<p>As the title suggests, there are two prevalent forms of PHP templating, each with its own cons and pros:</p>
<ul>
<li>
<p>Search-and-replace systems (to which Smarty belongs) involve running string replacement filters on a template, replacing placeholders with dynamic content.Search-and-replace systems suffer from parsing overhead which can be significant depending on the amount of content being parsed. More advanced systems in this category attempt to offset the overhead by caching parse results (Smarty for example relies heavily on caching for its performance), but this introduces the concern of maintaining the cache (determining when it becomes stale).</p>
<p>Search-and-replace systems are also better suited for serving mostly static content, as regenerating content dynamically incurs the parsing overhead. Hence it is more suited for content web-sites than highly dynamic web-applications, in which every user sees a different page than the others, limiting the effectiveness of caching.</p>
</li>
<li>
<p> Include systems involve including PHP scripts which serve as templates, and passing variables directly to those. Wordpress for example uses a basic implementation of such a system for its templating mechanism.Include systems suffer much less overhead for parsing templates than search-and-replace schemes, simply due to the fact that no such action takes place.</p>
<p>On the other hand, include systems are prone to scoping problems. If templates are included in the normal flow of the application, then they share and pollute the scope they are in - meaning they could affect data in other parts of the application which could lead to weird behavior and decrease in reusability of templates.</p>
</li>
</ul>
<h2>Templating with Objects</h2>
<p>Ideally, we would like to combine the pros and solve the cons of both systems. We need a way to pass an arbitrary number of variables into a template without polluting the general scope of the application, while avoiding the parsing overhead of search-and-replace routines.</p>
<p>Fortunately PHP presents us with such a construct - Classes. Class methods are different from regular functions in that they have a shared local scope always available - the object instance ($this). Recent PHP templating systems use this property of classes to their advantage, creating a separate scope for templates thereby allowing them to process without affecting the rest of the application.</p>
<p><a title="Savant" href="http://phpsavant.com/" target="_blank">Savant</a> is a good example of such a system, and so is the <a href="http://framework.zend.com/manual/en/zend.view.html" target="_blank">View</a> component of the Zend Framework. I'll be borrowing concepts from both to show how a simple implementation of such a system can be built.</p>
<h2>In Code</h2>
<p>In the most basic form, a templating system built with the principles I've mentioned above will look like this:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000000; font-weight: bold;">class</span> View <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">     <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$script</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <a href="http://www.php.net/ob_start"><span style="color: #000066;">ob_start</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <span style="color: #0000ff;">$this</span>-&gt;_include<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$script</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <span style="color: #b1b100;">return</span> <a href="http://www.php.net/ob_get_clean"><span style="color: #000066;">ob_get_clean</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __get<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    	<span style="color: #b1b100;">return</span> <span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span> -&gt; <span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#41;</span> ? <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #0000ff;">$key</span> : <span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    protected <span style="color: #000000; font-weight: bold;">function</span> _include<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <span style="color: #b1b100;">include</span> <a href="http://www.php.net/func_get_arg"><span style="color: #000066;">func_get_arg</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #66cc66;">&#125;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li></ol></pre>
<p>Usage is pretty simple - load some vars into a View class instance and pass a template into the render method. For a template that looks like:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&lt;h2&gt;&lt;?php <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #006600;">name</span>; ?&gt;&lt;/h2&gt;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><a href="http://www.php.net/current"><span style="color: #000066;">Current</span></a> position: <span style="color: #000000; font-weight: bold;">&lt;?php</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #006600;">job</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li></ol></pre>
<p>Passing parameters into a view instance:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0000ff;">$view</span> = <span style="color: #000000; font-weight: bold;">new</span> View<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0000ff;">$view</span> -&gt; <span style="color: #006600;">name</span> = <span style="color: #ff0000;">'Obama'</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0000ff;">$view</span> -&gt; <span style="color: #006600;">job</span> = <span style="color: #ff0000;">'President of the USA'</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$view</span> -&gt; <span style="color: #006600;">render</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/path/to/template.phtml'</span><span style="color: #66cc66;">&#41;</span>;</div></li></ol></pre>
<p>Will result in:</p>
<pre class="html4strict"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/h2.html"><span style="color: #000000; font-weight: bold;">&lt;h2&gt;</span></a></span>Obama<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/h2&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Current position: President of the USA</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li></ol></pre>
<p>We can also invoke the render() method inside a template to chain several templates together:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&lt;h2&gt;&lt;?php <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #006600;">name</span>; ?&gt;&lt;/h2&gt;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><a href="http://www.php.net/current"><span style="color: #000066;">Current</span></a> position: <span style="color: #000000; font-weight: bold;">&lt;?php</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #006600;">position</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #006600;">render</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'footer.phtml'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li></ol></pre>
<p>'footer.phtml' being another separate template file.</p>
<h2>In Review</h2>
<p>Lets review what the class does:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">     <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$script</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <a href="http://www.php.net/ob_start"><span style="color: #000066;">ob_start</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <span style="color: #0000ff;">$this</span>-&gt;_include<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$script</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <span style="color: #b1b100;">return</span> <a href="http://www.php.net/ob_get_clean"><span style="color: #000066;">ob_get_clean</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li></ol></pre>
<p>The render() method receives a $script parameter which is the path to a template script. It passes that parameter to separate method called _include() and captures the output using output buffering.</p>
<p>Capturing the output into a string instead of outputting to the screen at once is very useful if we want to perform this as a part of a complete process, such as preparing headers and starting sessions(), which has to happen before any output is sent to the browser. It is also useful in case we want to perform additional transformations on the output before sending it to the browser (such as parsing and filtering).</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    protected <span style="color: #000000; font-weight: bold;">function</span> _include<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">        <span style="color: #b1b100;">include</span> <a href="http://www.php.net/func_get_arg"><span style="color: #000066;">func_get_arg</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #66cc66;">&#125;</span></div></li></ol></pre>
<p>The _include() method is the core of this templating approach. By including the template inside a class method with no arguments (calling func_get_arg() instead), the included script has only the object instance ($this) as the available scope to get information from and pass information to. Any variables we declare inside this scope have no bearing on the outside and so collisions and scoping issues are avoided.</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">     <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __get<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    	<span style="color: #b1b100;">return</span> <span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span> -&gt; <span style="color: #0000ff;">$key</span><span style="color: #66cc66;">&#41;</span> ? <span style="color: #0000ff;">$this</span> -&gt; <span style="color: #0000ff;">$key</span> : <span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span>;</div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #66cc66;">&#125;</span></div></li></ol></pre>
<p>This is really a utility method to prevent PHP from throwing a 'variable is not defined' notice in case the template attempts to access a non existing parameter.</p>
<p>Complete solutions like Zend_View and Savant offer many more features, such as plug-ins, filters, base directory configuration and more, but the principle is the same. While the same structure could be mimicked to some degree using procedural functions only, the simple and convenient interface of passing and retrieving parameter to/from templates is unique to this approach - making it the clear winner in my opinion.</p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=135" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=QuNo8Y6rSIs:y6PqngiawxM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=QuNo8Y6rSIs:y6PqngiawxM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=QuNo8Y6rSIs:y6PqngiawxM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=QuNo8Y6rSIs:y6PqngiawxM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=QuNo8Y6rSIs:y6PqngiawxM:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/QuNo8Y6rSIs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2008/11/18/oo-php-templating/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2008/11/18/oo-php-templating/</feedburner:origLink></item>
		<item>
		<title>Making web-pages go faster using PHP</title>
		<link>http://feedproxy.google.com/~r/Techfounder/~3/KkSYXPMfdCM/</link>
		<comments>http://www.techfounder.net/2008/11/16/making-web-pages-go-faster-using-php/#comments</comments>
		<pubDate>Sun, 16 Nov 2008 04:52:06 +0000</pubDate>
		<dc:creator>Eran Galperin</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://www.techfounder.net/?p=121</guid>
		<description><![CDATA[UI responsiveness is one of the basics of a good user experience. In the web environment, this often translates to the loading time of pages.
As it might be expected, there are several techniques to optimize the delivery of web pages. The Exceptional Performance guide by Yahoo is a great resource for a multitude of optimizations [...]]]></description>
			<content:encoded><![CDATA[<p>UI responsiveness is <a href="http://www.useit.com/papers/responsetime.html" target="_blank">one of the basics</a> of a good user experience. In the web environment, this often translates to the loading time of pages.</p>
<p>As it might be expected, there are several techniques to optimize the delivery of web pages. The <a title="Yahoo Exceptional Performance" href="http://developer.yahoo.com/performance/" target="_blank">Exceptional Performance</a> guide by Yahoo is a great resource for a multitude of optimizations practices, including specifically two techniques which I will address in this article - script <a title="Yahoo on minifying javascript" href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_8.html" target="_blank">minifcation</a> and <a title="The Yahoo blog on combining scripts" href="http://yuiblog.com/blog/2008/07/21/performance-research-part-6/" target="_blank">concatenation</a>.<br />
<span id="more-121"></span></p>
<h2>Reducing script size and the number of request</h2>
<p>Modern web sites and web application serve increasingly heavier javascript and CSS files. The price for the increase in script payload is felt both on the client side, where loading time increase making pages feel slugish, and on the server side, where bandwidth and requests are at a premium.</p>
<p>Javascript files especially block the browser while downloading (no more than 2 components can be downloaded simultaneously as per <a title="HTML Specifications HTTP/1.1" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.4" target="_blank">HTML specifications</a>), and are the type of scripts seeing the steepest increase in size in the last several years.</p>
<h2>Minification and concatenation</h2>
<p>Minifying is the process of removing all unnecessary characters from the source code without changing its functionality (removing whitespaces, line-breaks and comments, replacing variables names and more). Concatenation is the process of unifying two strings into one. Applying both to our scripts we reduce total script size and the amount of requests.</p>
<p>There are several public algorithms for minifying Javascript, and Dean Edwards gives <a title="Dean Edward on Javascript compression" href="http://dean.edwards.name/weblog/2007/08/js-compression/" target="_blank">a nice overview of those</a> on his blog.</p>
<p>For PHP we have the handy <a href="http://code.google.com/p/minify/" target="_blank">Minify</a> library, which handles both the minifcation and concatenation of scripts. Minify is quite robust, and comes with <a href="http://code.google.com/p/minify/wiki/ComponentClasses" target="_blank">a set of standalone classes</a> that can be used in other contexts as well. It also sets Etags and far-future headers for better client script caching.</p>
<h2>Deploying Minify</h2>
<p>Downloading and extracting the <a href="http://minify.googlecode.com/files/release_2.1.1.zip">package available</a> on google code creates several text files and two sub-directories. The directory that is of interest to us is '/min' which contains the actual source code, and we'll place it somewhere on our server about our document root (so it can be accessed by a regular http request).</p>
<p>The basic workflow of using Minify is to replace our &lt;script&gt; and &lt;link&gt; tags which load our javascript and CSS respectively with calls to the minify script. We need to tell the Minify script which scripts to process, and there are two main ways to accomplish that:</p>
<p> - Passing the scripts as parameters in the call to the minify script. We pass the path to the scripts separated by commas, translating the following:</p>
<pre class="html4strict"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">&lt;script</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/path/to/script_one.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">&lt;script</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/path/to/script_two.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></span></div></li></ol></pre>
<p>Into:</p>
<pre class="html4strict"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">&lt;script</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/path/to/min/?f=/path/to/script_one.js,/path/to/script_two.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></span></div></li></ol></pre>
<p>There is actually a shorter way writing this, by using a common base path for both scripts:</p>
<pre class="html4strict"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">&lt;script</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/path/to/min/?b=path/to&amp;f=script_one.js,script_two.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></span></div></li></ol></pre>
<p>Provided that all the paths are correct, we have successful concatenated two scripts into one minified script. This can repeated for as many scripts as we like, though there is an artificial limit (due to performance and memory limitations I assume) of 10 scripts per Minify request. This limit can be adjusted in the configuration file which exists at the base path of the library (config.php).</p>
<p> - Using pre-defined script arrays. This method is less flexible as it requires hardcoding the script names into an array, but is slightly more performant. Minify calls those array 'groups', which look something like:</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"> <span style="color: #b1b100;">return</span> <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">    <span style="color: #ff0000;">'js'</span> =&gt; <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'//path/to/script_one.js'</span>, <span style="color: #ff0000;">'//path/to/script_two.js'</span><span style="color: #66cc66;">&#41;</span></div></li><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#41;</span>;</div></li></ol></pre>
<p>You can find an example of those in the installation folder of Minify (groupsConfig.php). The request to the script is then made by specifying the group name:</p>
<pre class="html4strict"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">&lt;script</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/path/to/min/?g=js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></span></div></li></ol></pre>
<p>There are several options when using groups, and you can read on those on the library's <a href="http://code.google.com/p/minify/w/list">wiki</a>.</p>
<p>Its important to set up the cache folder for Minify. Minifying the scripts can actually take a couple of seconds, which is a relatively long delay - however once generated once they will be cached until the scripts change (provided the cache folder is set-up properly). </p>
<p>To declare the cache folder, simply define a variable named $min_cachePath in the configuration file or the main app file before the main application start.</p>
<pre class="php"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0000ff;">$min_cachePath</span> = <span style="color: #ff0000;">'/path/to/cache'</span>;</div></li></ol></pre>
<p>Make sure the folder exists and has write permissions by PHP.</p>
<h2>Real world use</h2>
<p>I've implemented Minify in all of my recent projects to great effect. An extreme case would be script deployment in my current startup, <a href="http://www.octabox.com">Octabox web platform</a>. Being a heavy-duty web-application, it consumes much more javascript and styles than your average marketing site.</p>
<h3>Without Minify</h3>
<p>Javascript requests:<br />
<img src="http://www.techfounder.net/wp-content/uploads/2008/11/js.gif" alt="Javascript" style="float:none;" /><br />
CSS requests:<br />
<img src="http://www.techfounder.net/wp-content/uploads/2008/11/css.gif" alt="CSS" style="float:none;" /></p>
<h3>With Minify</h3>
<p>Javascript requests:<br />
<img src="http://www.techfounder.net/wp-content/uploads/2008/11/minifiedjs.gif" alt="Minified Javascript" style="float:none;" /><br />
CSS requests:<br />
<img src="http://www.techfounder.net/wp-content/uploads/2008/11/minifiedcss.gif" alt="Minified CSS" style="float:none;" /></p>
<p>51 total requests weighing 540kb reduced to 5 requests weighing 116kb. </p>
 <img src="http://www.techfounder.net/wp-content/plugins/feed-statistics.php?view=1&post_id=121" width="1" height="1" style="display: none;" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Techfounder?a=KkSYXPMfdCM:cTvPjJ2cjvc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Techfounder?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=KkSYXPMfdCM:cTvPjJ2cjvc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=KkSYXPMfdCM:cTvPjJ2cjvc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Techfounder?a=KkSYXPMfdCM:cTvPjJ2cjvc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Techfounder?i=KkSYXPMfdCM:cTvPjJ2cjvc:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Techfounder/~4/KkSYXPMfdCM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.techfounder.net/2008/11/16/making-web-pages-go-faster-using-php/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://www.techfounder.net/2008/11/16/making-web-pages-go-faster-using-php/</feedburner:origLink></item>
	</channel>
</rss>
