
<?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</title>
	<atom:link href="http://www.drewcking.com/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>New, code-friendly blog theme</title>
		<link>http://www.drewcking.com/2009/03/new-code-friendly-blog-theme/</link>
		<comments>http://www.drewcking.com/2009/03/new-code-friendly-blog-theme/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 10:09:03 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[Blog / SEO]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=46</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 finally upgraded my Wordpress installation to 2.7.1, and while I was at it I decided to change the theme to something that makes reading code snippets a little bit easier.  The previous theme I was using limited each code block to about 450px in width, plus it felt a little bit too dark. [...]]]></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 finally upgraded my Wordpress installation to 2.7.1, and while I was at it I decided to change the theme to something that makes reading code snippets a little bit easier.  The previous theme I was using limited each code block to about 450px in width, plus it felt a little bit too dark. Now, running this <a href="http://imotta.cn/" target="_blank">Coogee</a> theme, I&#8217;ve got a total of 660px worth of content width.</p>
<p>I&#8217;m also trying out the <a href="http://www.google.com/url?sa=U&#038;start=1&#038;q=http://wordpress.org/extend/plugins/wp-super-cache" target="_blank">WP Super Cache</a> plugin to speed things up.  I don&#8217;t get very much traffic here, but Wordpress takes <i>much</i> longer to load than I&#8217;m accustomed to, so I thought I&#8217;d try the cache route. It makes a huge difference.  My main blog index was taking over 3 seconds to fully load, as timed by Firefox&#8217;s YSlow plugin.  With the cache enabled, it&#8217;ll load in about 0.3 seconds.  Ahh.</p>
<p>Hopefully all my old posts and comments are displaying properly.  There&#8217;s some odd character encoding issues that I need to sort out, but if you notice any glaring problems, like broken links or errors, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2009/03/new-code-friendly-blog-theme/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL-like AUTO_INCREMENT in PostgreSQL</title>
		<link>http://www.drewcking.com/2008/12/mysql-like-auto_increment-in-postgresql/</link>
		<comments>http://www.drewcking.com/2008/12/mysql-like-auto_increment-in-postgresql/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 19:33:11 +0000</pubDate>
		<dc:creator>Drew</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.drewcking.com/?p=42</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>
 Lately I&#8217;ve been forcing myself to learn PostgreSQL as a replacement for MySQL.  In my experimentation, one of the first things I had to figure out how to do was simulate auto-incrementing.  In MySQL it&#8217;s as simple as sticking the word AUTO_INCREMENT in the column definition, but PostgreSQL doesn&#8217;t have that.  What [...]]]></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>Lately I&#8217;ve been forcing myself to learn PostgreSQL as a replacement for MySQL.  In my experimentation, one of the first things I had to figure out how to do was simulate auto-incrementing.  In MySQL it&#8217;s as simple as sticking the word <code>AUTO_INCREMENT</code> in the column definition, but PostgreSQL doesn&#8217;t have that.  What it has instead is a totally separate database object called a <a href="http://www.postgresql.org/docs/7.4/interactive/functions-sequence.html" target="new"><code>SEQUENCE</code></a>, which is essentially just a single-row table used especially to provide for this type of functionality.</p>
<p>For example, in order to create a simple table to store user records, you&#8217;d first create the sequence that will be used to generate the unique user IDs:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> SEQUENCE user_seq</pre></div></div>

<p>Then create the <code>user</code> table and tell its <code>user_id</code> column to use the sequence as the default value:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> user
<span style="color: #66cc66;">&#40;</span>
  user_id INTEGER <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NEXTVAL</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'user_seq'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  email CHARACTER VARYING<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  password CHARACTER<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">40</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>After this, the first <code>user</code> record that is inserted will get a value of 1, and successive insertions will be incremented appropriately, just like AUTO_INCREMENT.</p>
<p>Because this is such a common practice, PostgreSQL lets you take a little shortcut, via the <a href="http://www.postgresql.org/docs/8.1/interactive/datatype.html#DATATYPE-SERIAL">SERIAL</a> column type (thought technically speaking, it&#8217;s not actually a true data type).  Using this, you can simply skip the sequence creation, and just specify your table like so:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> user
<span style="color: #66cc66;">&#40;</span>
  user_id SERIAL<span style="color: #66cc66;">,</span>
  email CHARACTER VARYING<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  password CHARACTER<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">40</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>This will create a sequence called <code>user_user_id_seq</code> behind the scenes (i.e., <i>table</i>_<i>column</i>_seq)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.drewcking.com/2008/12/mysql-like-auto_increment-in-postgresql/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>
	</channel>
</rss>
