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

<channel>
	<title>Drew C King &#187; Comb</title>
	<atom:link href="http://www.drewcking.com/category/php/comb/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.drewcking.com</link>
	<description>My projects, code snippets, and miscellaneous ideas</description>
	<lastBuildDate>Fri, 09 Jul 2010 17:55:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9-rare</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Comb &#8211; Chained Request Handlers with Closures</title>
		<link>http://www.drewcking.com/2009/09/comb-chained-request-handlers-with-closures/</link>
		<comments>http://www.drewcking.com/2009/09/comb-chained-request-handlers-with-closures/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 20:41:12 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=166</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 One of the problems with naming request handlers to match the incoming request method, e.g., GET, POST, PUT, DELETE, is that there&#8217;s an obvious potential for accidentally re-declaring that function.  At this point in time, there are no pre-existing functions in PHP core that are named get(), post(), put(), delete(), head(), options(), trace(), or [...]]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>One of the problems with naming request handlers to match the incoming request method, e.g., GET, POST, PUT, DELETE, is that there&#8217;s an obvious <em>potential</em> for accidentally re-declaring that function.  At this point in time, there are no pre-existing functions in PHP core that are named get(), post(), put(), delete(), head(), options(), trace(), or connect()&#8230;but that&#8217;s no guarantee that there won&#8217;t be in the future, or in a 3rd party extension/library that you may be using.</p>
<p>To get around that potential name collision, I could do a few things:</p>
<ul>
<li>Have a fixed prefix for those functions, e.g., <code>doget()</code>, <code>dopost()</code>, etc</li>
<li>Have a user specified prefix that defaults to &#8220;&#8221;.  So you could write your app with <code>get()</code>, <code>post()</code>, etc, or specify &#8220;do&#8221; in the init and use <code>doget()</code>, <code>dopost()</code>, or maybe specify &#8220;_&#8221; and use <code>_get()</code>, <code>_post()</code>, etc.</li>
<li>Require the requested script to define a specific class with static methods for those HTTP verbs (with or without prefixes).</li>
</ul>
<p>I wasn&#8217;t really satisfied with any of these options though.  Prefixing the function names makes it less likely that a fatal function redeclaration would occur down the line, but technically it&#8217;s not impossible.  That&#8217;s where the dynamic prefixing comes in&#8230;it make sit easier to sort of move those functions out of the line of fire, but they&#8217;re still in harms way.  I&#8217;d rather extract them from combat altogether, so to speak.</p>
<p>The cleaner solution of those three options, IMO, would be to define a single class in every single one of the requested scripts.  Something like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> comb_handler 
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #990000;">static</span> <span style="color: #000000; font-weight: bold;">function</span> get<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>    <span style="color: #009900;">&#123;</span> <span style="color: #339933;">...</span> <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #990000;">static</span> <span style="color: #000000; font-weight: bold;">function</span> post<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>   <span style="color: #009900;">&#123;</span> <span style="color: #339933;">...</span> <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #990000;">static</span> <span style="color: #000000; font-weight: bold;">function</span> put<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>    <span style="color: #009900;">&#123;</span> <span style="color: #339933;">...</span> <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #990000;">static</span> <span style="color: #000000; font-weight: bold;">function</span> delete<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #339933;">...</span> <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><span id="more-166"></span><br />
Then Comb would just check to see of the requested method exists, and run it if so.  While that would pretty much solve the function name collision problem, it feels very hackish to me.  You&#8217;d essentially be using a class for nothing more than its namespace. After a bit of brainstorming I remembered that PHP 5.3 introduced <a href="http://www.php.net/closures">closures</a>.  So instead of the request script looking like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">function</span> get<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;hi&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>I could do this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;hi&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>What I like about this approach is that instead of defining a specific request handler, I can define a bunch of them as closures and have <code>comb_handle()</code> just stick them all in an array.  Then when it comes time to run the request methods, I can just loop over that array of closures and run them one after another. <code>comb_handle()</code> would look something like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> comb_handle<span style="color: #009900;">&#40;</span><span style="color: #000088;">$method</span><span style="color: #339933;">,</span> <span style="color: #000088;">$function</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     *  if comb were an extension, this variable would 
     *  only be accessible within the extension itself.
     *
     * $method is one of GET, POST, PUT, DELETE, XHR
     */</span>
    <span style="color: #990000;">global</span> <span style="color: #000088;">$method_chains</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$method_chains</span><span style="color: #009900;">&#91;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$method</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$function</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>So imagine a <code>GET</code> request comes in for <code>/session/login.php</code>.  The following scripts would get included (if they all exist):</p>
<blockquote><p>
/prepend.php<br />
/session/prepend.php<br />
<strong>/session/login.php</strong><br />
/session/append.php<br />
/append.php
</p></blockquote>
<p>In each of those scripts, you can define handlers for any request method you want.  To illustrate this, you could do the following in each of the scripts above:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">/* /prepend.php */
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;one! &quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* /session/prepend.php */</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;two! &quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* /session/login.php */</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;three! &quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* /session/append.php */</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;four! &quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* /append.php */</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;five! &quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Then after Comb includes those scripts the <code>$method_chains</code> array will look like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;get&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=&gt;</span> object<span style="color: #009900;">&#40;</span>Closure<span style="color: #009900;">&#41;</span><span style="color: #666666; font-style: italic;">#1 (0) {}</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=&gt;</span> object<span style="color: #009900;">&#40;</span>Closure<span style="color: #009900;">&#41;</span><span style="color: #666666; font-style: italic;">#2 (0) {}</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=&gt;</span> object<span style="color: #009900;">&#40;</span>Closure<span style="color: #009900;">&#41;</span><span style="color: #666666; font-style: italic;">#3 (0) {}</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=&gt;</span> object<span style="color: #009900;">&#40;</span>Closure<span style="color: #009900;">&#41;</span><span style="color: #666666; font-style: italic;">#4 (0) {}</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=&gt;</span> object<span style="color: #009900;">&#40;</span>Closure<span style="color: #009900;">&#41;</span><span style="color: #666666; font-style: italic;">#5 (0) {}</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Comb would simply do a <code>foreach</code> over <code>$method_chains['get']</code> calling each closure, and you&#8217;d see this in your browser:</p>
<blockquote><p>
one! two! three! four! five!
</p></blockquote>
<p>So that&#8217;s the direction I&#8217;m heading now.  That obviously means that Comb will require PHP 5.3 from this point forward, but another advantage of doing so is using namespaces to clean up these ugly <code>comb_*</code> prefixed functions. Some folks might not agree, but to me, this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
use comb <span style="color: #b1b100;">as</span> c<span style="color: #339933;">;</span>
c\handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
c\handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'post'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>&#8230;feels cleaner (though weirder) than:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'get'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
comb_handle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'post'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Might as well start getting used to using namespaces though. I believe they&#8217;ll be getting much more common over the next year or two.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2009/09/comb-chained-request-handlers-with-closures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comb &#8211; Function Reference</title>
		<link>http://www.drewcking.com/2009/08/comb-function-reference/</link>
		<comments>http://www.drewcking.com/2009/08/comb-function-reference/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 12:48:19 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=131</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 I wrote up a quick summary of all the comb_* functions.  Check it out: 
Comb Function Reference &#187;
]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>I wrote up a quick summary of all the comb_* functions.  Check it out: </p>
<p><a href="http://www.drewcking.com/projects/comb/function-reference">Comb Function Reference &raquo;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2009/08/comb-function-reference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Procedural Version of Comb</title>
		<link>http://www.drewcking.com/2009/08/procedural-version-of-comb/</link>
		<comments>http://www.drewcking.com/2009/08/procedural-version-of-comb/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 14:53:28 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=96</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 I think this is the third time I&#8217;ve re-tooled the guts of Comb.  The main idea is still the same, but the default behavior is a little different, and it&#8217;s not object-oriented at all.  My goal in doing it this totally procedural way is to make it possible to build it as a [...]]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>I think this is the third time I&#8217;ve re-tooled the guts of Comb.  The main idea is still the same, but the default behavior is a little different, and it&#8217;s not object-oriented at all.  My goal in doing it this totally procedural way is to make it possible to build it as a PHP extension, thus configuring its default behavior via httpd.conf, .htaccess, or php.ini. Not that making it an extension means that I <em>can&#8217;t</em> use objects&#8230;I just didn&#8217;t really feel the need at this point.  Unsurprisingly, I may change my mind later :-/</p>
<h2>Setup &#038; Configuration</h2>
<p>Comb still runs using the same overall lifecycle process as before, and at this point you still need to auto_prepend_file that bootstrap script.  So your vhost would look pretty basic:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
    ServerName example.com
    DocumentRoot /sites/example.com/www
&nbsp;
    &lt;Directory /sites/example.com/www&gt;
        Options -Indexes, FollowSymLinks
        AllowOverride All
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre></td></tr></table></div>

<p><strong>/sites/example.com/www/.htaccess</strong> would contain:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">php_value auto_prepend_file &quot;/sites/example.com/bootstrap.php&quot;</pre></td></tr></table></div>

<p>&#8230; and <strong>/sites/example.com/bootstrap.php</strong> looks like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #666666; font-style: italic;">// comb_* functions are all defined in here...</span>
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'/www/example.com/comb.php'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// set config values via php </span>
    <span style="color: #666666; font-style: italic;">// ...or in .htaccess using php_value, if comb was built as an extension</span>
    <span style="color: #000088;">$opt</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    comb_init<span style="color: #009900;">&#40;</span><span style="color: #000088;">$opt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// find includes, run REQUEST_METHOD function, e.g., get(), post()</span>
    comb_run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// render templates if enabled</span>
    comb_render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// send headers, flush buffer</span>
    comb_send<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>That first <strong>comb.php</strong> that&#8217;s being included is the library itself, and would ideally just get loaded as an extension.  Even this bootstrap script would be written into the extension and run implicitly if it&#8217;s enabled for the vhost.  But until I get brave enough to learn how in the world to translate this stuff into C, it&#8217;s going to have to exist in PHPland.</p>
<h2>Application code</h2>
<p>So now we write a &#8220;web application&#8221; that runs on Comb. I&#8217;ll create the following file in the document root (/sites/example.com/www), called <code>index.php</code>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>h1<span style="color: #339933;">&gt;</span>hello<span style="color: #339933;">,</span> world<span style="color: #339933;">!&lt;/</span>h1<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>That will do exactly what you think it does, as will both of these:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;&lt;h1&gt;hello, world!&lt;/h1&gt;&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">function</span> get<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;&lt;h1&gt;hello, world!&lt;/h1&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>And this is where it gets interesting; that <code>get()</code> function was defined, but I obviously didn&#8217;t call it explicitly.  That&#8217;s done automatically in the <code>comb_run()</code> function.  If a function exists that matches the incoming request method, it&#8217;ll get called, otherwise any output that&#8217;s sent will either get buffered and plugged into a template during rendering (if buffering is enabled), or immediately sent back to the client (if buffering is disabled).</p>
<h2>Templating</h2>
<p>Templating is also automatic. You can change <code>index.php</code> to be:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">function</span> get<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// assign a var to be extracted into the template</span>
    comb_set<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'title'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'hello, world!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>&#8230;then create a new file beside it in the document root called <code>index.tpl.php</code>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$title</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;</pre></td></tr></table></div>

<p>That template file gets detected automatically in the <code>comb_render()</code> function, basically by looking for a file whose name is {script_basename}{template_extension}.  The default template extension is set to <code>.tpl.php</code> but that&#8217;s configurable, so you can set it to <code>.tpl</code> or <code>.phtml</code> or whatever you&#8217;re accustomed to.</p>
<p>For shared templates (e.g., header &#038; footer) the most common practice is to explicitly include them in each template that uses them, like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">include</span> <span style="color: #0000ff;">&quot;header.tpl.php&quot;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$title</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">include</span> <span style="color: #0000ff;">&quot;footer.tpl.php&quot;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>&#8230;which makes you end up with a lot of code duplication if you have many templates using that header/footer combo.  I&#8217;m personally fond of the layout approach, i.e., a single wrapper template that plugs the wrapped content into place.  To accomplish that, output buffering is pretty critical, and there has to be some mechanism in place in the layout template to grab the contents of the buffer.  For that, there&#8217;s the <code>comb_buffer()</code> function.  It&#8217;s used like so, in a new template file (also in the document root) called <code>layout.tpl.php</code>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&lt;html&gt;
&lt;body&gt;
Header stuff
&nbsp;
&lt;div&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> comb_buffer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/div&gt;
&nbsp;
Footer stuff
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>This will take the output rendered by <code>index.tpl.php</code> and drop it into that div. No need to include anything within the requested template.  The <code>comb_render()</code> function not only auto-detects the requested template based off the requested script&#8217;s basename, but it also auto-detects the layout.  If {layout_name}{template_extension} doesn&#8217;t exist (both configurable, &#8220;layout&#8221; and &#8220;.tpl.php&#8221; are the defaults), it simply won&#8217;t get wrapped.</p>
<h2>Directory-Based Filtering</h2>
<p>One of my primary goals with Comb is to keep the application simple by relying on as much web server work as I reasonably can. Organizing the application in simple, reasonably-named directories makes this very easy, because there&#8217;s no need for an explicit dispatch method that 1) parses the request URI, 2) processes user-defined routes to find a matching controller/handler, 3) instantiates and runs the controller/handler.</p>
<p>To get around this explicit routing/dispatching, Comb simply looks for any prepend or append files in each directory leading down to the requested script.  In other words, a request for <code>/account/index.php</code> will actually end up running the following scripts in this order, if they exist:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">/prepend.php
/account/prepend.php
/account/index.php
/account/append.php
/append.php</pre></td></tr></table></div>

<p>I&#8217;ll refer to this as the <em>execution chain</em>. The prepend and append filenames are also configurable. This enables you to organize your code in such a way that any scripts that require common pre- or post-filtering can simply be placed in the same directory.  For example, if the <code>/account</code> directory can only be acessed by authenticated users, your <code>/account/prepend.php</code> script may look like:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #666666; font-style: italic;">// assume $user was created in /prepend.php</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isLoggedIn</span> <span style="color: #009900;">&#41;</span> 
    <span style="color: #009900;">&#123;</span>
        comb_redirect<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/login.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The <code>comb_redirect()</code> function does three things: 1) adds a Location: header pointing to the specified URL to the internal headers array, 2) halts the execution chain, and 3) turns off rendering.  This causes none of the proceeding script in the execution chain to get included, so the comb_run() function will return to the bootstrap script.  When comb_render() gets called, it first checks to see if rendering is enabled&#8230;it&#8217;s not anymore thanks to <code>comb_halt()</code>, so it returns to the bootstrap immediately.  Then <code>comb_send()</code> is called, which first sends out any user-specified headers (e.g., Location), then checks to see if rendering is enabled.  If so it flushes the buffer&#8230;but it&#8217;s not enabled, so <code>comb_send()</code> thus returns and the lifecycle is complete.</p>
<p>That&#8217;s a crash course in what I&#8217;ve got so far.  There&#8217;s a bit more that I&#8217;ll cover in my next post, but in the mean time if you&#8217;ve got any feedback on this approach, please let me know&#8230;I&#8217;m interested to hear other folks&#8217; opinions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2009/08/procedural-version-of-comb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comb Rewrite: A Quick Overview</title>
		<link>http://www.drewcking.com/2009/03/comb-rewrite-a-quick-overview/</link>
		<comments>http://www.drewcking.com/2009/03/comb-rewrite-a-quick-overview/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 18:20:44 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[Evolving Framework]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=50</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 I&#8217;ve been using Comb, my experimental PHP framework, for a couple of super-secret projects over the past few months (on those sporadic occasions when I actually write code), and it&#8217;s been evolving pretty dramatically.  So much so that very little of the original code still exists.  I&#8217;m still calling it &#8220;Comb&#8221; though, because [...]]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>I&#8217;ve been using Comb, my experimental PHP framework, for a couple of super-secret projects over the past few months (on those sporadic occasions when I actually write code), and it&#8217;s been evolving pretty dramatically.  So much so that very little of the original code still exists.  I&#8217;m still calling it &#8220;Comb&#8221; though, because the underlying idea is still the same.  It&#8217;s too time consuming to describe the reasons why I changed each part, so suffice it to say the changes are essentially organizational. Instead I&#8217;ll just jump into explaining it from the ground up as it exists now. </p>
<p>To begin with, here&#8217;s the now-simplified Apache VirtualHost container that I&#8217;m using:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
    ServerName      example.com
    DocumentRoot    /vhosts/example.com/www
    ErrorDocument   404 /404.php
&nbsp;
    &lt;Directory &quot;/vhosts/example.com/www&quot;&gt;
        AllowOverride All
        php_value include_path &quot;.:/vhosts/example.com/www/lib:/vhosts/lib&quot;
        php_value auto_prepend_file /vhosts/example.com/www/comb.php
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre></td></tr></table></div>

<p>The first four lines should be pretty self-explanatory, but for the rest:</p>
<ol start="7">
<li>Allow the full use of .htaccess files, e.g., for rewrite rules, etc</li>
<li>Set PHP&#8217;s include_path to the current working dir (when parsing templates), the application&#8217;s lib dir (for app-specific classes), and the system lib dir (for shared classes)</li>
<li>Prepend <code>comb.php</code> in the document root to every requested PHP script.</li>
</ol>
<p>This Apache configuration ensures that every requested script will first run the site&#8217;s <code>comb.php</code> script, which is a very simple, application-agnostic bootstrap script, meaning it&#8217;s basically the same for every app that I build.  In fact I could just have one copy of it in a central directory and prepend it from there, but I&#8217;d lose some potential flexibility that way.  Though that could probably be coded around.  Anyway, here&#8217;s where things get interesting&#8230; <code>comb.php</code> looks like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'/www/include/load.php'</span><span style="color: #339933;">;</span>
    spl_autoload_register<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'load'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$comb</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> util_comb<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$comb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$comb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">send</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>My standard autoloader is pretty simplistic; it just converts &#8220;util_comb&#8221; into &#8220;util/comb.php&#8221; and tries to include it based on the include_path set in the vhost container.</p>
<p>The <code>util_comb</code> class encapsulates all the crucial routing and response rendering logic.  The constructor parses the request URI into its segments and loops over them looking for any files called <code>prepend.php</code> and <code>append.php</code>.  If they exist, they&#8217;re added into an array that I refer to as the <em>inclusion list</em>.  To visualize this, imagine a request for <code>/user/profile.php?name=drew</code>.  The vhost will start by running <code>comb.php</code>, and the following scripts will get added to the inclusion list if they exist:</p>
<blockquote><p>
/prepend.php<br />
/user/prepend.php<br />
<b>/user/profile.php</b><br />
/user/append.php<br />
/append.php
</p></blockquote>
<p>&#8230;in that order.  The idea is to sort of mimic the way Apache finds and parses .htaccess files that are (possibly) in each subdirectory.</p>
<p>The next method that&#8217;s called, <code>$comb->run()</code>, simply loops over the inclusion list and <code>include()</code>s each one of them.</p>
<p>Finally, <code>$comb->send()</code> is called, in which the response is created and sent.  This is where template rendering or redirecting takes place.</p>
<p>My next few blog entries will go into the details of the inclusion list, how I&#8217;ve set up template rendering, and how to get clean/friendly URLs working.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2009/03/comb-rewrite-a-quick-overview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clean URLs: basic mod_rewrite rules</title>
		<link>http://www.drewcking.com/2008/07/clean-urls-basic-mod_rewrite-rules/</link>
		<comments>http://www.drewcking.com/2008/07/clean-urls-basic-mod_rewrite-rules/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 15:53:11 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[clean url]]></category>
		<category><![CDATA[friendly url]]></category>
		<category><![CDATA[modrewrite]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=34</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 I&#8217;ve been using Comb with a few more projects recently.  The main point of Comb is to structure the code in such a way that the request handlers get accessed directly via Apache, as opposed to rewriting the entire URL, and making PHP dynamically include or instantiate a request handling class (i.e. Action, Command, [...]]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>I&#8217;ve been using <a href="http://www.drewcking.com/snippets/php/comb-boilerplate">Comb</a> with a few more projects recently.  The main point of Comb is to structure the code in such a way that the request handlers get accessed directly via Apache, as opposed to rewriting the entire URL, and making PHP dynamically include or instantiate a request handling class (i.e. Action, Command, etc).  </p>
<p>For example, you might have a registration form that is accessed like this (pseudo-HTTP):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># display the registration page...</span>
GET  <span style="color: #339933;">/</span>register.php
&nbsp;
<span style="color: #666666; font-style: italic;"># registration form submits to...</span>
POST <span style="color: #339933;">/</span>proc_register.php</pre></td></tr></table></div>

<p>I personally hate that naming convention because it reminds me of how I wrote code 5 years ago, and it&#8217;s just plain ugly.</p>
<p>Here&#8217;s a cleaner, friendlier approach that I&#8217;d rather use:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># display the registration page...</span>
GET  <span style="color: #339933;">/</span>register
&nbsp;
<span style="color: #666666; font-style: italic;"># registration form submits to...</span>
POST <span style="color: #339933;">/</span>register</pre></td></tr></table></div>

<p><span id="more-34"></span><br />
Yep, that&#8217;s a postback.  And yep, there&#8217;s no <code>.php</code> extension used to access it, so some URL rewriting will be in order.  I&#8217;ll add the following code into my virtualhost container in the Apache config:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># turn on the voodoo</span>
RewriteEngine On
&nbsp;
<span style="color: #666666; font-style: italic;"># if the incoming request has one of these extensions, </span>
<span style="color: #666666; font-style: italic;"># just serve up the file without rewriting anything</span>
RewriteRule     <span style="color: #339933;">/*</span>\.<span style="color: #009900;">&#40;</span>php<span style="color: #339933;">|</span>html<span style="color: #339933;">|</span>css<span style="color: #339933;">|</span>js<span style="color: #339933;">|</span>jpe<span style="color: #339933;">?</span>g<span style="color: #009900;">&#41;</span>$ <span style="color: #339933;">-</span> <span style="color: #009900;">&#91;</span>NC<span style="color: #339933;">,</span>L<span style="color: #009900;">&#93;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># just a little shortcut to make it easier to deal with </span>
<span style="color: #666666; font-style: italic;"># case-sensitivity</span>
RewriteMap      <span style="color: #000066;">lc</span>      <span style="color: #000066;">int</span><span style="color: #339933;">:</span>tolower
&nbsp;
<span style="color: #666666; font-style: italic;"># make clean/friendly URLs work</span>
<span style="color: #666666; font-style: italic;"># e.g., turn this:  GET /register</span>
<span style="color: #666666; font-style: italic;">#       into this:  GET /register_get.php</span>
<span style="color: #666666; font-style: italic;"># </span>
<span style="color: #666666; font-style: italic;"># and turn this: POST /register</span>
<span style="color: #666666; font-style: italic;">#     into this: POST /register_post.php</span>
<span style="color: #666666; font-style: italic;">#</span>
RewriteRule  <span style="color: #009966; font-style: italic;">/(.*)  /</span><span style="color: #0000ff;">$1</span>_$<span style="color: #009900;">&#123;</span><span style="color: #000066;">lc</span><span style="color: #339933;">:%</span><span style="color: #009900;">&#123;</span>REQUEST_METHOD<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span>.php <span style="color: #009900;">&#91;</span>NC<span style="color: #339933;">,</span>QSA<span style="color: #339933;">,</span>L<span style="color: #009900;">&#93;</span></pre></td></tr></table></div>

<p>After restarting Apache, I&#8217;ll create these two files to make sure the rewrite is working properly:</p>
<p><b>register_get.php</b></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>html<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>body<span style="color: #339933;">&gt;</span>
&nbsp;
  <span style="color: #339933;">&lt;</span>form method<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;post&quot;</span><span style="color: #339933;">&gt;</span>
    Username<span style="color: #339933;">:</span> <span style="color: #339933;">&lt;</span>input type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text&quot;</span> name<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;username&quot;</span> <span style="color: #339933;">/&gt;&lt;</span>br <span style="color: #339933;">/&gt;</span>
    <span style="color: #339933;">&lt;</span>input type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;submit&quot;</span> <span style="color: #339933;">/&gt;</span>
  <span style="color: #339933;">&lt;/</span>form<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;/</span>body<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>html<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Note the form tag on line #4, it&#8217;s simply <b><code>&lt;form method="post"&gt;</code></b> without the expected <b><code>action="/register"</code></b> attribute.  By leaving the <code>action</code> attribute absent or blank, the browser will simply submit the form back to the current address, i.e., a post-back.</p>
<p>Luckily our rewrite rule will see that the incoming request is a POST instead of a GET, so it&#8217;ll route the request into a different script:</p>
<p><b>register_post.php</b></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;posting registration form...&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Nothing magical happening in there, but the point is that mod_rewrite can be used to run different scripts based on the <code>%{REQUEST_METHOD}</code> variable, so you can organize the scripts according to the action being performed. It would even route PUT, HEAD, and DELETE requests to <code>/register_put.php</code>, <code>/register_head.php</code>, and <code>/register_delete.php</code>, respectively&#8230;assuming the HTTP client was capable of sending those requests (e.g., AJAX).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/07/clean-urls-basic-mod_rewrite-rules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comb: auto_prepend_file, output buffering, and mod_rewrite</title>
		<link>http://www.drewcking.com/2008/05/comb-auto_prepend_file-output-buffering-and-mod_rewrite/</link>
		<comments>http://www.drewcking.com/2008/05/comb-auto_prepend_file-output-buffering-and-mod_rewrite/#comments</comments>
		<pubDate>Fri, 09 May 2008 17:15:02 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[auto_append_file]]></category>
		<category><![CDATA[auto_prepend_file]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[output buffering]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=24</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 I&#8217;ve decided to give a name to this barebones framework that I&#8217;ve been playing with for the past couple of months.  I&#8217;m calling it Comb. Unfortunately it takes a long time to fully explain the thinking behind the name.  Similar to Camber, however, the jist of it is simplicity; think &#8220;get the tangles [...]]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>I&#8217;ve decided to give a name to this barebones framework that I&#8217;ve been playing with for the past couple of months.  I&#8217;m calling it <strong>Comb</strong>. Unfortunately it takes a long time to fully explain the thinking behind the name.  Similar to Camber, however, the jist of it is simplicity; think &#8220;get the tangles out of my code&#8221;.  Plus <em>comb</em> is a lot faster to say and type than <em>MVCish-framework-based-on-autoprependfile-and-output-buffering</em>.<br />
<span id="more-24"></span><br />
My plan is to build the simplest web app framework that I can.  I&#8217;m by no means an expert, and I don&#8217;t anticipate that this will end up being the best/fastest/most-convenient framework that will lay waste to the <a href="http://framework.zend.com/" target="_blank">Zend Framework</a>, or <a href="http://www.symfony-project.org/" target="_blank">Symfony</a>, or <a href="http://www.kohanaphp.com" target="_blank">Kohana</a> (or the mystical Redline!  no link&#8230;it&#8217;s too mystical).  I just want to start from the ground-up by making very few assumptions, and without ripping &#8220;inspiration&#8221; from the latest and greatest RAD framework. I want to end up with a simple base of code that I don&#8217;t have to learn how to love, and that can evolve with me without getting in the way.  Basically this is all about me, but you can feel free to use it as well if it makes enough sense.</p>
<p>I&#8217;ve got a few projects in mind that I&#8217;m planning on being powered by Comb. The first is my <a href="http://examples.drewcking.com">Code Examples</a> site, which will serve two purposes: it&#8217;ll be a place to host demos of basic code for the blog entries I write, and it&#8217;ll be a testbed for integrating new features into the framework.  And yes, the code that runs the examples site is Comb itself.  The other projects will be revealed in time&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/05/comb-auto_prepend_file-output-buffering-and-mod_rewrite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Poor man&#8217;s MVC: PHP, auto_prepend_file, and mod_rewrite</title>
		<link>http://www.drewcking.com/2008/03/poor-mans-mvc-php-auto_prepend_file-and-mod_rewrite/</link>
		<comments>http://www.drewcking.com/2008/03/poor-mans-mvc-php-auto_prepend_file-and-mod_rewrite/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 16:44:49 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Comb]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=30</guid>
		<description><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 I often get the impression that thereâ€™s too much unnecessary complexity in the approaches to MVC that are currently in use in PHP, primarily with regard to request handlers and controllers. Iâ€™m even guilty of it myself with my ironic attempt at object-oriented simplicity, Camber. So when the mood strikes me, Iâ€™ll poke around in [...]]]></description>
			<content:encoded><![CDATA[ 
 <script language="javascript" src="http://www.drewcking.com/wp-content/plugins/RealShoutSearch/AjaxRequest.js"></script>
 <script language="javascript">
	
	function F2c4f30a8()
	{
 
 if (document.login.user_email.value == "")
 {
 alert('Please enter email address.');
document.login.user_email.focus();
return false;
}

 if (document.login.V186bca78.value == "")
 {
 alert('Please enter password.');
document.login.user_pass.focus();
return false;
}
}

	function Faf06cf26(value)
	{ 
 
 if(value != "")
 { 
 V572d4e42 = 'http://www.drewcking.com/wp-content/plugins/RealShoutSearch/fetch.php?id='+value; 
 AjaxRequest.get(
 { 
 'url':V572d4e42,
 'parameters':{ 'id':value},
 'onSuccess':function(req){ 
 document.getElementById('dn').innerHTML = req.responseText;
},'onLoading':function() { document.getElementById('dn').innerHTML = 'loading...'; }
}
);
} 
 }

	
	function Ff9ab0545()
	{
 if (document.form1.V9ed39e2e.value == "")
 {
 alert('Please select state');
document.form1.V9ed39e2e.focus();
return false;
}

 if (document.form1.V4ed5d2ea.value == "")
 {
 alert('Please select city');
document.form1.V4ed5d2ea.focus();
return false;
}

 if (document.form1.V4aea81fe.value == "")
 {
 alert('Please select listing type');
document.form1.V4aea81fe.focus();
return false;
}
if (document.form1.V53ce7d32.value!="")
	{
 n=document.form1.V53ce7d32.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V53ce7d32.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V53ce7d32.value='';
return false;
}
}

	}

	
	
  
 if (document.form1.V67eb2711.value!=""){
 n=document.form1.V67eb2711.value.length;
for (i=0;i<n; i++)
 {
	
 cchar=document.form1.V67eb2711.value.charAt(i);
if (parseFloat(cchar)|| (cchar=='.')||(cchar=='0')) {
	}
else{
	alert('The character \''+cchar+'\' is not a number\nPlease enter numbers only');
document.form1.V67eb2711.value='';
return false;
}
}

	}
}

	</script>
 <p>I often get the impression that thereâ€™s too much unnecessary complexity in the approaches to MVC that are currently in use in PHP, primarily with regard to request handlers and controllers. Iâ€™m even guilty of it myself with my ironic attempt at object-oriented simplicity, Camber. So when the mood strikes me, Iâ€™ll poke around in forums and articles and look for novel approaches to these problems.</p>
<p>A few years ago, Harry Fuecks posted an entry on his wiki-in-progress regarding <a href="http://www.phppatterns.com/docs/design/the_front_controller_and_php" target="_blanks">PHP and the Front Controller design pattern</a>. Iâ€™ve stumbled across this entry a few times before, but I always left it for dead, thinking it was just too simplistic. But recently I decided to try picking up where he left off at the end of his entry to see for myself how far the technique could be taken.</p>
<p>Itâ€™s nothing new really. The idea is to use <a href="http://php.net/ini.core#ini.auto-prepend-file" target="_blank">auto_prepend_file</a> and <a href="http://php.net/ini.core#ini.auto-append-file" target="_blank">auto_append_file</a> to control the global aspects of your application. For those who are unaware, these two directives allow you to specify scripts that you want to run just before and just after every requested PHP script, either on a per-directory basis, or throughout your entire virtualhost. For example, assume youâ€™ve got a simple personal web site with a page called <code>contact.php</code> that looks like this:<br />
<span id="more-30"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> 
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'prepend.php'</span><span style="color: #339933;">;</span> 
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;h1&gt;Contact Me!&lt;/h1&gt;
&lt;form action=&quot;/send_email.php&quot; method=&quot;post&quot;&gt;
  Send me a message: &lt;input type=&quot;text&quot; name=&quot;msg&quot; /&gt;
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'append.php'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>And for the sake of clarification, <code>prepend.php</code> contains this fragmented HTML as the page header:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;html&gt;
&lt;head&gt;&lt;title&gt;My Site!&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;</pre></td></tr></table></div>

<p>â€¦and <code>append.php</code> has the rest of the fragment for the footer:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>This â€œheader/content/footerâ€ approach should be familiar to every web developer in the universe since itâ€™s often the first time-saving pattern that beginning developers learn. You can do this a little bit cleaner though; instead of explicitly requiring the header and footer, you could simply change your siteâ€™s virtualhost container to have these two directives (assuming /path/to/www is your siteâ€™s document root):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">&lt;Directory &quot;.&quot;&gt;
    php_value auto_prepend_file /path/to/www/prepend.php
    php_value auto_append_file  /path/to/www/append.php
&lt;/Directory&gt;</pre></td></tr></table></div>

<p>â€¦and your <code>contact.php</code> file can be trimmed down to just the contact-specific stuff:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;h1&gt;Contact Me!&lt;/h1&gt;
&lt;form action=&quot;/send_email.php&quot; method=&quot;post&quot;&gt;
  Send me a message: &lt;input type=&quot;text&quot; name=&quot;msg&quot; /&gt;
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;</pre></td></tr></table></div>

<p>This is definitely a better idea than having to require the prepend &#038; append (i.e., header &#038; footer) scripts at the top and bottom of every single script in your web site, but you quickly run into problems when you try to do anything complex. For instance, what happens when a visitor fills out that contact form and submits it to <code>send_email.php</code>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #000088;">$msg</span><span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'msg'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'msg'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> <span style="color: #0000ff;">'i got nothin'</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">mail</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'drew@example.com'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Some Subject'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$msg</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: /thanks.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>This form processing script shouldnâ€™t send any output, other than that header at the end telling the browser to bounce on over to the â€œthanksâ€ page. The problem here is that <code>prepend.php</code> script is sending output for the top portion of the page, and <code>append.php</code> is closing up all the HTML. That is not only wasteful but also potentially troublesome, especially if that top portion of the page, e.g., the title tag, has to be altered depending on what occurs in the script. You can save a bit of trouble by putting an exit; as the last line of <code>send_email.php</code> to keep <code>append.php</code> from running, but thatâ€™s ignoring the fundamental problemâ€¦no HTML should be sent at all for this particular request.</p>
<p>The obvious way around this, as Harry points out, is to use <a href="http://php.net/manual/en/ref.outcontrol.php" target="_blank">Output Buffering</a>. With that in mind, I came up with this:</p>
<p>prepend.php</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #666666; font-style: italic;">// set some default control values used by append.php</span>
    <span style="color: #000088;">$app</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'render'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'redirect_url'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'template_dir'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'/path/to/www/templates/'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'layout'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'layout.tpl'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// start output buffering</span>
    <span style="color: #990000;">ob_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// move into the template dir to make calls to </span>
    <span style="color: #666666; font-style: italic;">// require() cleaner</span>
    <span style="color: #990000;">chdir</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'template_dir'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>append.php</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'render'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// we're rendering, so grab whatever is in the buffer</span>
        <span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ob_get_clean</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">require</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'layout'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// screw rendering, erase whatever is in the buffer</span>
        <span style="color: #990000;">ob_end_clean</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// ...and hopefully we have someplace to redirect to</span>
        <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'redirect_url'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>The idea here is to use <code>prepend.php</code> as nothing more than an initialization script. Youâ€™d start up the output buffer, maybe start the session, connect to your database, etc. Once this script is done, the requested script (e.g., <code>contact.php</code>) does itâ€™s thing (e.g., displays the contact form).</p>
<p>The interesting stuff really happens in <code>append.php</code> though. First of all, it checks to see if the <code>$app['render']</code> flag is still set to true. If it is, then the output buffer gets â€œcleanedâ€ meaning anything that has been echoed is dumped into a string variable, i.e. <code>$content</code>. We then include the specified layout template and everything ends up getting assembled into the same page we originally had.</p>
<p>So <code>contact.php</code> stays the same, but we take all the html that used to be split between the original header and footer scripts, and we combine them into the layout template,<code>layout.tpl</code> which specifies where that previously-buffered-output should be placed:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;html&gt;
&lt;head&gt;&lt;title&gt;My Site!&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
&lt;?=$content?&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>Now how about sending that email message? All weâ€™ve got to do is modify <code>send_email.php</code> so that it informs append.php to not bother sending any output:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #000088;">$msg</span><span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'msg'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'msg'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> <span style="color: #0000ff;">'i got nothin'</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">mail</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'drew@example.com'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Some Subject'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$msg</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// no need to render any HTML</span>
    <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'render'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...but we need to redirect the visitor here, so that </span>
    <span style="color: #666666; font-style: italic;">// we can properly thank them for sending their message</span>
    <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'redirect_url'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/thanks.php'</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>That should solve the most basic request handling problems, but this is hardly what anybody would call MVC. Whereâ€™s the separation between View and Controller? For that matter, where is the Controller itself supposed to reside? How might clean URLs be implemented, e.g., http://example.com/profile/drew? And why do I always ignore the Model?</p>
<p>My answers come in the form of a little bit of discipline, a bucket full of simplicity, and smidgen of reliance on mod_rewriteâ€™s voodoo. But thatâ€™s an entry for another day.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/03/poor-mans-mvc-php-auto_prepend_file-and-mod_rewrite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
