
<?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; PHP</title>
	<atom:link href="http://www.drewcking.com/category/php/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>Redline Web App Engine, Day 1</title>
		<link>http://www.drewcking.com/2009/08/redline-web-app-engine-day-1/</link>
		<comments>http://www.drewcking.com/2009/08/redline-web-app-engine-day-1/#comments</comments>
		<pubDate>Sat, 15 Aug 2009 15:40:15 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Redline]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=79</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>
 Sean Kerr built and currently maintains a simple web application engine (&#8217;tain&#8217;t a framework!) called Redline.  He and a few other guys I know (Wess &#038; Brandon) have raved about the deadly speed+simplicity of it for quite awhile now, so I thought I&#8217;d give it a go with a site I&#8217;m building for my [...]]]></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><a href="http://www.code-box.org/">Sean Kerr</a> built and currently maintains a simple web application engine (&#8217;tain&#8217;t a framework!) called <a href="http://www.code-box.org/redline">Redline</a>.  He and a few other guys I know (<a href="http://www.wattz.net/">Wess</a> &#038; <a href="http://www.think-done.com/">Brandon</a>) have raved about the deadly speed+simplicity of it for quite awhile now, so I thought I&#8217;d give it a go with a site I&#8217;m building for my day job.<br />
<span id="more-79"></span><br />
To begin, I set up a basic vhost container in Apache in which to drop the RL 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="text" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
    ServerName redline.local
    DocumentRoot /sites/redline.local/www
&nbsp;
    &lt;Directory /sites/redline.local/www&gt;
        Options -Indexes, FollowSymLinks
        AllowOverride All
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre></td></tr></table></div>

<p>Then I create the site directory, download the Redline package from Sean&#8217;s site, and unzip it:</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="text" style="font-family:monospace;"> drew@server$  mkdir -p /sites/redline.local
 drew@server$  cd /sites/redline.local
 drew@server$  wget http://code-box.org/work/redline-0.1.zip
 drew@server$  unzip redline-0.1.zip
 drew@server$  cp -R redline-0.1/* .
 drew@server$  rm -rf redline-0.1/</pre></td></tr></table></div>

<p>At this point, the contents of my <code>/sites/redline.local/</code> directory is:</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="text" style="font-family:monospace;"> cache/
 config.xml
 docs/
 lib/
 modules/
 tags/
 www/</pre></td></tr></table></div>

<p>Redline expects all requests to be rewritten through the document root&#8217;s <code>www/index.php</code> script in order to properly dispatch each request.  To get that running right, I create the following  <code>.htaccess</code> file under <code>www/</code>:</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="text" style="font-family:monospace;">RewriteEngine On
&nbsp;
# don't rewrite the index script, or any CSS, javascript, or image files
RewriteRule ^(index\.php|js|css|images) - [NC,L]
&nbsp;
# everything else goes through the index bootstrap
RewriteRule (.*) index.php/$1 [L]</pre></td></tr></table></div>

<p>Another problem I ran into is that the dispatcher parses <code>$_SERVER['PATH_INFO']</code> in order to determine what&#8217;s being requested, but for some reason on my VirtualBox server (Ubuntu 8.10, Apache2) I don&#8217;t have that variable available.  I googled a bit to find out how to get it set, but the most sensible solution (AcceptPathInfo On) didn&#8217;t pan out either.  Instead, I cracked open Redline&#8217;s <code>config.xml</code> and told it to use <code>REQUEST_URI</code> instead of <code>PATH_INFO</code>:</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;!-- request path details --&gt;
    &lt;define name=&quot;RL_PATH_INFO&quot;&gt;REQUEST_URI&lt;/define&gt;
..</pre></td></tr></table></div>

<p>Redline is built to parse that XML config and generate a PHP script that gets stored under the <code>cache/</code> directory, which means that directory will need to be writable for the user that Apache runs as (www-data, nobody, apache, etc). There are a few ways to handle this, but the quick and dirty option is to just <code>chmod 777 cache</code>, which effectively gives every user on the server read/write access to everything in that directory.  Since I own the whole machine it&#8217;s not a security concern, but in a shared environment you&#8217;d want to take a slightly less shotgun approach (assuming it&#8217;s an issue at all).</p>
<p>Next I edit my hosts file so that <code>redline.local</code> resolves to my server&#8217;s IP address, and I give it a test run by pointing my browser to <code>http://redline.local/redline</code>, which loads up the example redline module provided in the package. And what do I see?</p>
<blockquote>
<h1>Welcome to Redline</h1>
</blockquote>
<p>Yay!  Next I&#8217;ll set up another module and explain what I&#8217;ve learned so far about routing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2009/08/redline-web-app-engine-day-1/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>Enums in PHP</title>
		<link>http://www.drewcking.com/2008/08/enums-in-php/</link>
		<comments>http://www.drewcking.com/2008/08/enums-in-php/#comments</comments>
		<pubDate>Fri, 15 Aug 2008 01:05:37 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=37</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 working on a project lately where I&#8217;m rolling my own basic role-based access control (RBAC) system.  In experimenting with different ways to handle the role definitions, I realized that it&#8217;d be pretty nice to have a basic enum() function or construct, as a quick, convenient way to define a set of constants. [...]]]></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 working on a project lately where I&#8217;m rolling my own basic role-based access control (RBAC) system.  In experimenting with different ways to handle the role definitions, I realized that it&#8217;d be pretty nice to have a basic <code>enum()</code> function or construct, as a quick, convenient way to define a set of constants.  There&#8217;s this option:</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: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ADMIN'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MODERATOR'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EDITOR'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</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>but that isn&#8217;t exactly succinct.  I&#8217;d rather have something 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>
    enum<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ADMIN'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'MODERATOR'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'EDITOR'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// ADMIN == 0 (true)</span>
    <span style="color: #666666; font-style: italic;">// MODERATOR == 1 (true), etc.</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>You can kind of mimic the enumerated values with arrays like so:<br />
<span id="more-37"></span></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: #000088;">$roles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'ADMIN'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'MODERATOR'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'EDITOR'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</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>but having to specify those values is just tedious.  There&#8217;s an easy trick to get around that though:</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="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #000088;">$roles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'ADMIN'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'MODERATOR'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'EDITOR'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$roles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_flip</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$roles</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">/*
    Array
    (
        [ADMIN] =&gt; 0
        [EDITOR] =&gt; 1
        [MODERATOR] =&gt; 2
    )
    */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Which is cool, but I want constants, not just array values.  Which is cleaner?<br/><br/> <code>if ($role == $roles['ADMIN'])</code><br/><code>if ($role == ADMIN)</code><br/><br/>So a bit more digging, and I found that APC can turn an array into a bunch of constants in one fell swoop!</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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Try loading the constants from APC
     */</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>apc_load_constants<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'roles'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #009933; font-style: italic;">/**
         * they aren't in APC, so make 'em and define 'em
         */</span>
        <span style="color: #000088;">$roles</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_flip</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'ADMIN'</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'EDITOR'</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'MODERATOR'</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        apc_define_constants<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'roles'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$roles</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Now we've got enumerated constants...
     *  ADMIN == 0
     *  MODERATOR == 1
     *  EDITOR == 2
     */</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Obviously you need APC to make this work.  One great thing about using <code>apc_load_constants()</code> is that you get a modest speed boost because you don&#8217;t have to <code>define()</code> all of your constants every time the script runs. Another benefit is that you can load up your array of roles (or whatever your constants are, e.g., permissions, etc.) from a database or other dynamic source, and convert them into global constants with one function call.  </p>
<p>Now what would be even cooler is if you could tell <code>apc_load_constants()</code> to load the constants into a specific namespace, maybe something 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>
    apc_load_constants<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'roles'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'drew'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;ADMIN's value: &quot;</span> <span style="color: #339933;">.</span> drew<span style="color: #339933;">::</span><span style="color: #004000;">ADMIN</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Though I assume that would require at least PHP 5.3.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/08/enums-in-php/feed/</wfw:commentRss>
		<slash:comments>2</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>Pagination with MySQL and FOUND_ROWS()</title>
		<link>http://www.drewcking.com/2008/07/pagination-with-mysql-and-found_rows/</link>
		<comments>http://www.drewcking.com/2008/07/pagination-with-mysql-and-found_rows/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 13:45:39 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[FOUND_ROWS]]></category>
		<category><![CDATA[pagination]]></category>
		<category><![CDATA[paging]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=32</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>
 Jody clued me into a convenient method of paginating a result set from MySQL.  Since he hasn&#8217;t blogged about it yet, I will >:-)
In the past, I&#8217;d issue two queries back to back, similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
&#60;?php
    $page = isset&#40;$_GET&#91;'page'&#93;&#41; ? &#40;int&#41; $_GET&#91;'page'&#93;: 1;
    $size = 10;
   [...]]]></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><a href="http://www.jodymickey.com">Jody</a> clued me into a convenient method of paginating a result set from MySQL.  Since he hasn&#8217;t blogged about it yet, I will >:-)</p>
<p>In the past, I&#8217;d issue two queries back to back, similar to this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</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;">$page</span> <span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$size</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$offset</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #000088;">$size</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> mysqli<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;drew&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;mypass&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;db&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT username FROM user LIMIT <span style="color: #006699; font-weight: bold;">$offset</span>, <span style="color: #006699; font-weight: bold;">$size</span>;&quot;</span>
         <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;SELECT COUNT(*) FROM user&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$users</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>
    <span style="color: #000088;">$total</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">multi_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">store_result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// fetch this page of user records</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$res</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetch_row</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$users</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// fetch the TOTAL number of users</span>
        <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">next_result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$total</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">store_result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetch_row</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$pages</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ceil</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$total</span><span style="color: #339933;">/</span><span style="color: #000088;">$size</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;Total Users: <span style="color: #006699; font-weight: bold;">$total</span>&lt;br&gt;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;Total Pages: <span style="color: #006699; font-weight: bold;">$pages</span>&lt;br&gt;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;Current Page: <span style="color: #006699; font-weight: bold;">$page</span>&lt;br&gt;&lt;br&gt;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$users</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$u</span><span style="color: #009900;">&#41;</span> <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$u</span>&lt;br&gt;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> 
        <span style="color: #990000;">echo</span> <span style="color: #0000ff;">'&lt;a href=&quot;?page='</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&quot;&gt;&amp;laquo; Prev&lt;/a&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$page</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$pages</span><span style="color: #009900;">&#41;</span> 
        <span style="color: #990000;">echo</span> <span style="color: #0000ff;">&quot; | &quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$page</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$pages</span><span style="color: #009900;">&#41;</span> 
        <span style="color: #990000;">echo</span> <span style="color: #0000ff;">'&lt;a href=&quot;?page='</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&quot;&gt;Next &amp;raquo;&lt;/a&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Take note of Line #8.  The first query grabs the specified page of results, the second simply does a full count of all rows so I could calculate the total number of pages.  </p>
<p>What sucks, however, is if the query is more complex, especially if the various parts of it have to be dynamically generated, e.g., table joins, conditions in the where clause, etc.  In such a case you&#8217;d have to change the second query to get rid of the column list <code>SELECT column1, column 2...</code> and make it <code>SELECT COUNT(*)</code>.  Also, you&#8217;d have to toss out any <code>ORDER BY</code> and <code>LIMIT</code> clauses.</p>
<p>MySQL allows you to simplify this extremely common scenario by using the <a href="http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows">FOUND_ROWS()</a> function. In the above code, you can simply modify the query itself:</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: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #666666; font-style: italic;">// ... change this:</span>
    <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT username FROM user LIMIT <span style="color: #006699; font-weight: bold;">$offset</span>, <span style="color: #006699; font-weight: bold;">$size</span>;&quot;</span>
         <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;SELECT COUNT(*) FROM user&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ... to this:</span>
    <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT SQL_CALC_FOUND_ROWS username FROM user LIMIT <span style="color: #006699; font-weight: bold;">$offset</span>, <span style="color: #006699; font-weight: bold;">$size</span>;&quot;</span>
         <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;SELECT FOUND_ROWS()&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>The rest of the code remains the same and will give you the exact same results.</p>
<p>The speed of this approach can vary depending on how you have your table(s) indexed, and the complexity of the query itself.  In other words, in some circumstances it may be faster to actually run the LIMITed query followed by the appropriate <code>SELECT COUNT(*) FROM ...</code> query as in the first example, but the primary benefit is in the simplification of the query itself.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/07/pagination-with-mysql-and-found_rows/feed/</wfw:commentRss>
		<slash:comments>1</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>Object-oriented controllers bug me</title>
		<link>http://www.drewcking.com/2008/03/object-oriented-controllers-bug-me/</link>
		<comments>http://www.drewcking.com/2008/03/object-oriented-controllers-bug-me/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 20:09:16 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=29</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 thought I might take a little step back here from my previous entry regarding my simplistic, not-all-that-original MVC using auto_prepend_file. I realized that I didnâ€™t really explain why I occasionally get in that â€œthereâ€™s-got-to-be-a-simpler-wayâ€ frame of mind.
As I was building Camber, I made it a point to stick with an object-oriented design as closely [...]]]></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 thought I might take a little step back here from my previous entry regarding my simplistic, not-all-that-original MVC using auto_prepend_file. I realized that I didnâ€™t really explain why I occasionally get in that â€œthereâ€™s-got-to-be-a-simpler-wayâ€ frame of mind.</p>
<p>As I was building Camber, I made it a point to stick with an object-oriented design as closely as possible. The bootstrap script (i.e., <code>index.php</code>) simply sets up the basic environment, creates the main objects that are needed for the application, and starts things flowing. To re-cap, the whole life-cycle for a request in a Camber application is:</p>
<ol>
<li>Create the <code>Application</code> object</li>
<li>Create the <code>Controller</code> object by passing in the <code>Application</code></li>
<li>Call <code>$controller->getResource()</code> which returns a <code>Resource</code> object</li>
<li>Call <code>$resource->run()</code>, which returns the <code>Response</code> object</li>
<li>Call <code>$response->send()</code> to send the response back</li>
</ol>
<p><span id="more-29"></span><br />
In general, I like the way the application itself is structured. Although any given <code>Resource</code> class (which is basically just a collection of request handlers, i.e. get(), post(), delete(), put()) might be pretty complex, itâ€™s fairly simple to figure out where each feature of the application should reside. Adding functionality to your application is really just a matter of writing new <code>Resource</code> classes and updating the templates appropriately. The thing that bothers me though is the routing process, i.e., determining which Resource needs to be instantiated for any given request.</p>
<p>Camberâ€™s routing logic is handled within the <code>Controller::getResource()</code> method, but I pretty much ignored building any kind of regular-expression-esque routing language. Instead of having a declarative way of specifying which <code>Resource</code> to create, my neglect requires the author to decide how to perform that instantiation. Maybe a bunch of big, ugly, nested <code>if()</code>s that examine the incoming URL, or a <code>switch()</code> statement that does the same. You could even write your own regular expressions to match the various parts of the URL and decide which <code>Resource</code> needs to be created and run. I know. Shame on me for not building that mechanism into the framework.</p>
<p>Anyway, the reason that this kind of in-framework routing bothers me is that it is implemented in PHP (either pre-built within the framework itself, or (even worse!) by the author of the application). Not only does that seem unnecessarily bulky, but it also requires some kind of loading mechanism that looks up the appropriate request handler. This can be accomplished in a relatively uncomplicated way by putting all of the request handlers in a special directory (e.g., controllers/), then just <code>require()</code>ing the appropriate class file depending on what your routing method returned and instantiating it.</p>
<p>Is that really necessary though? Imagine a simple web application where an HTTP request for:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">http://example.com/profile/display?name=drew</pre></div></div>

<p>will result in the following code being executed (use your imagination to fill in the gaps):</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;">// ...routing code runs here...</span>
    <span style="color: #666666; font-style: italic;">// determines the following from the request:</span>
    <span style="color: #666666; font-style: italic;">//   $controller     = 'profile'</span>
    <span style="color: #666666; font-style: italic;">//   $action         = 'display'</span>
    <span style="color: #666666; font-style: italic;">//   $params['name'] = 'drew'</span>
&nbsp;
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'controllers/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$controller</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'.php'</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$controller</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'Controller'</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000088;">$controller</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;">// i.e., $c-&gt;display(array('name' =&gt; 'drew'));</span>
    <span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...finish up, send response...</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Itâ€™s not a whole bunch of code, but I donâ€™t think it needs to exist at all. Basically, instead of mapping requests to request handler classes, loading them, instantiating them, and running them, I propose simply using mod_rewrite and the natural file system structure in the document root to run the scripts that are being requested. This way, instead of declaring and implementing routing rules in PHP, youâ€™d just use the appropriate mod_rewrite rules. Instead of dynamically instantiating a request handler, you just let apache serve up the whichever PHP script happens to match the rewrite rule.</p>
<p>Obviously, this would mean that the request handler isnâ€™t an object at all; itâ€™s, for the most part, a regular old PHP script. Is that so bad though? There are definitely many conveniences that object-oriented request handlers can provide, such as using inheritance to specify things like authentication and authorization in the target request handlers. I believe, however, that itâ€™s possible to abide by the same DRY (Donâ€™t Repeat Yourself) principles for these specific requirements without relying on an unnecessarily complex object-oriented controller design.</p>
<p>The overarching idea here is to use the web server to handle as much of the grunt work of the application as possible before actually handing off control into PHP land.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/03/object-oriented-controllers-bug-me/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
