<?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>Richard Knop&#039;s Zend Framework Blog &#187; MySQL</title>
	<atom:link href="http://blog.richardknop.com/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.richardknop.com</link>
	<description>Zend Framework, PHP, MySQL, jQuery, JavaScript, AJAX, SEO, E-commerce and more</description>
	<lastBuildDate>Mon, 06 Sep 2010 15:49:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>How to register a new phpBB user with Zend Framework</title>
		<link>http://blog.richardknop.com/2010/05/how-to-register-a-new-phpbb-user-with-zend-framework/</link>
		<comments>http://blog.richardknop.com/2010/05/how-to-register-a-new-phpbb-user-with-zend-framework/#comments</comments>
		<pubDate>Thu, 20 May 2010 21:44:02 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[phpBB]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=580</guid>
		<description><![CDATA[You might need to integrate one of your future Zend Framework applications with phpBB forum software. The most important aspect of such integration is a dual sign up process. In other words, you want to avoid having users sign up at both the application and phpBB forum. The simplest solution is to have a single [...]]]></description>
			<content:encoded><![CDATA[<p>You might need to integrate one of your future Zend Framework applications with <a href="http://www.phpbb.com/">phpBB</a> forum software. The most important aspect of such integration is a dual sign up process. In other words, you want to avoid having users sign up at both the application and phpBB forum. The simplest solution is to have a single sign up form in your ZF application which upon submission will register user details in both your application and the phpBB forum. I will show you how to do that assuming both applications are on the same server.</p>
<p>The sign up form should have at least these fields:</p>
<ul>
<li>email</li>
<li>username</li>
<li>password</li>
</ul>
<div class="geshi no php">
<div class="head">// first of all, let&#39;s get the submitted form data</div>
<ol>
<li class="li1">
<div class="de1"><span class="re1">$data</span> <span class="sy0">=</span> <span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">getValues</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// here you would use the data to register user in the ZF application</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// once the user has been registered at the application level,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// let&#39;s use the same data to register him/her at the phpBB level</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$db</span> <span class="sy0">=</span> Zend_Registry<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st0">&#39;dbAdapter&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$phpbbUserIp</span> <span class="sy0">=</span> <span class="st0">&#39;127.0.0.1&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// if IP is valid include it in the INSERT query</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$validator</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Validate_Ip<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$validator</span><span class="sy0">-&gt;</span><span class="me1">isValid</span><span class="br0">&#40;</span><span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&#39;REMOTE_ADDR&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$phpbbUserIp</span> <span class="sy0">=</span> <span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&#39;REMOTE_ADDR&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;INSERT INTO phpbb_users (</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_type,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;group_id,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_permissions,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;username,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;username_clean,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_password,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_email,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_email_hash,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_timezone,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_lang,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_ip,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_regdate,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;user_dateformat)</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp;VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Db_Statement_Pdo<span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$this</span><span class="sy0">-&gt;</span>_helper<span class="sy0">-&gt;</span><span class="me1">PhpbbHash</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">sprintf</span><span class="br0">&#40;</span><span class="st0">&#39;%u&#39;</span><span class="sy0">,</span> <span class="kw3">crc32</span><span class="br0">&#40;</span><span class="kw3">strtolower</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">1.00</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;sk&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$phpbbUserIp</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;D M d, Y g:i a&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="re1">$stmt</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Db_Statement_Pdo<span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;SELECT user_id FROM phpbb_users WHERE user_email = ? LIMIT 1&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="re1">$userId</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchColumn</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="re1">$stmt</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Db_Statement_Pdo<span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;INSERT INTO phpbb_user_group (</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;group_id,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user_id,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;group_leader,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;user_pending)</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;VALUES (?, ?, ?, ?)&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="re1">$userId</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">7</span><span class="sy0">,</span> <span class="re1">$userId</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>There are few tiny things you will probably need to modify according to your application. I chose Slovak language (&#8216;sk&#8217;) and GMT+1 time zone (&#8217;1.00&#8242;) which is a time for central Europe. I also used a controller action helper PhpbbHash above. The helper is here:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* PhpbbHash</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* Just a phpbb hashing algorithm rewritten in a form of controller action helper.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* The reason for this is because we want users to be registered simultaneously</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* at both the main website and the phpbb forum so we will need to add a row to</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* phpbb_users table during registration at the main website.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* @author PHPBB</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">class</span> My_Controller_Action_Helper_PhpbbHash <span class="kw2">extends</span> Zend_Controller_Action_Helper_Abstract</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> direct<span class="br0">&#40;</span><span class="re1">$password</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$itoa64</span> <span class="sy0">=</span> <span class="st0">&#39;./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random_state</span> <span class="sy0">=</span> <span class="st0">&#39;123456789012&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$count</span> <span class="sy0">=</span> <span class="nu0">6</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re1">$fh</span> <span class="sy0">=</span> <span class="sy0">@</span><span class="kw3">fopen</span><span class="br0">&#40;</span><span class="st0">&#39;/dev/urandom&#39;</span><span class="sy0">,</span> <span class="st0">&#39;rb&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random</span> <span class="sy0">=</span> <span class="kw3">fread</span><span class="br0">&#40;</span><span class="re1">$fh</span><span class="sy0">,</span> <span class="re1">$count</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fclose</span><span class="br0">&#40;</span><span class="re1">$fh</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$random</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="re1">$count</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$count</span><span class="sy0">;</span> <span class="re1">$i</span> <span class="sy0">+=</span> <span class="nu0">16</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random_state</span> <span class="sy0">=</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="st0">&#39;123456789012&#39;</span> <span class="sy0">.</span> <span class="re1">$random_state</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random</span> <span class="sy0">.=</span> <span class="kw3">pack</span><span class="br0">&#40;</span><span class="st0">&#39;H*&#39;</span><span class="sy0">,</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="re1">$random_state</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$random</span> <span class="sy0">=</span> <span class="kw3">substr</span><span class="br0">&#40;</span><span class="re1">$random</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="re1">$count</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$hash</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_hash_crypt_private<span class="br0">&#40;</span><span class="re1">$password</span><span class="sy0">,</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_hash_gensalt_private<span class="br0">&#40;</span><span class="re1">$random</span><span class="sy0">,</span> <span class="re1">$itoa64</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="re1">$itoa64</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$hash</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">34</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$hash</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="re1">$password</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> _hash_gensalt_private<span class="br0">&#40;</span><span class="re1">$input</span><span class="sy0">,</span> <span class="sy0">&amp;</span><span class="re1">$itoa64</span><span class="sy0">,</span> <span class="re1">$iteration_count_log2</span> <span class="sy0">=</span> <span class="nu0">6</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$iteration_count_log2</span> <span class="sy0">&lt;</span> <span class="nu0">4</span> <span class="sy0">||</span> <span class="re1">$iteration_count_log2</span> <span class="sy0">&gt;</span> <span class="nu0">31</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$iteration_count_log2</span> <span class="sy0">=</span> <span class="nu0">8</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">=</span> <span class="st0">&#39;$H$&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$itoa64</span><span class="br0">&#91;</span><span class="kw3">min</span><span class="br0">&#40;</span><span class="re1">$iteration_count_log2</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw2">PHP_VERSION</span> <span class="sy0">&gt;=</span> <span class="nu0">5</span><span class="br0">&#41;</span> ? <span class="nu0">5</span> <span class="sy0">:</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="nu0">30</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_hash_encode64<span class="br0">&#40;</span><span class="re1">$input</span><span class="sy0">,</span> <span class="nu0">6</span><span class="sy0">,</span> <span class="re1">$itoa64</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$output</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> _hash_encode64<span class="br0">&#40;</span><span class="re1">$input</span><span class="sy0">,</span> <span class="re1">$count</span><span class="sy0">,</span> <span class="sy0">&amp;</span><span class="re1">$itoa64</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$value</span> <span class="sy0">=</span> <span class="kw3">ord</span><span class="br0">&#40;</span><span class="re1">$input</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="sy0">++</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$itoa64</span><span class="br0">&#91;</span><span class="re1">$value</span> <span class="sy0">&amp;</span> 0x3f<span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$count</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$value</span> <span class="sy0">|=</span> <span class="kw3">ord</span><span class="br0">&#40;</span><span class="re1">$input</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$itoa64</span><span class="br0">&#91;</span><span class="br0">&#40;</span><span class="re1">$value</span> <span class="sy0">&gt;&gt;</span> <span class="nu0">6</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span> 0x3f<span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$i</span><span class="sy0">++</span> <span class="sy0">&gt;=</span> <span class="re1">$count</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$count</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$value</span> <span class="sy0">|=</span> <span class="kw3">ord</span><span class="br0">&#40;</span><span class="re1">$input</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">16</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$itoa64</span><span class="br0">&#91;</span><span class="br0">&#40;</span><span class="re1">$value</span> <span class="sy0">&gt;&gt;</span> <span class="nu0">12</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span> 0x3f<span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$i</span><span class="sy0">++</span> <span class="sy0">&gt;=</span> <span class="re1">$count</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$itoa64</span><span class="br0">&#91;</span><span class="br0">&#40;</span><span class="re1">$value</span> <span class="sy0">&gt;&gt;</span> <span class="nu0">18</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span> 0x3f<span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$count</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$output</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> _hash_crypt_private<span class="br0">&#40;</span><span class="re1">$password</span><span class="sy0">,</span> <span class="re1">$setting</span><span class="sy0">,</span> <span class="sy0">&amp;</span><span class="re1">$itoa64</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">=</span> <span class="st0">&#39;*&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Check for correct hash</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">substr</span><span class="br0">&#40;</span><span class="re1">$setting</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="st0">&#39;$H$&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$output</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$count_log2</span> <span class="sy0">=</span> <span class="kw3">strpos</span><span class="br0">&#40;</span><span class="re1">$itoa64</span><span class="sy0">,</span> <span class="re1">$setting</span><span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$count_log2</span> <span class="sy0">&lt;</span> <span class="nu0">7</span> <span class="sy0">||</span> <span class="re1">$count_log2</span> <span class="sy0">&gt;</span> <span class="nu0">30</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$output</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$count</span> <span class="sy0">=</span> <span class="nu0">1</span> <span class="sy0">&lt;&lt;</span> <span class="re1">$count_log2</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$salt</span> <span class="sy0">=</span> <span class="kw3">substr</span><span class="br0">&#40;</span><span class="re1">$setting</span><span class="sy0">,</span> <span class="nu0">4</span><span class="sy0">,</span> <span class="nu0">8</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$salt</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="nu0">8</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$output</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; * We&#39;re kind of forced to use MD5 here since it&#39;s the only</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; * cryptographic primitive available in all versions of PHP</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; * currently in use.  To implement our own low-level crypto</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; * in PHP would result in much worse performance and</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; * consequently in lower iteration counts and hashes that are</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; * quicker to crack (by non-PHP code).</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp; */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw2">PHP_VERSION</span> <span class="sy0">&gt;=</span> <span class="nu0">5</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$hash</span> <span class="sy0">=</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="re1">$salt</span> <span class="sy0">.</span> <span class="re1">$password</span><span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$hash</span> <span class="sy0">=</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="re1">$hash</span> <span class="sy0">.</span> <span class="re1">$password</span><span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="sy0">&#8211;</span><span class="re1">$count</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$hash</span> <span class="sy0">=</span> <span class="kw3">pack</span><span class="br0">&#40;</span><span class="st0">&#39;H*&#39;</span><span class="sy0">,</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="re1">$salt</span> <span class="sy0">.</span> <span class="re1">$password</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$hash</span> <span class="sy0">=</span> <span class="kw3">pack</span><span class="br0">&#40;</span><span class="st0">&#39;H*&#39;</span><span class="sy0">,</span> <span class="kw3">md5</span><span class="br0">&#40;</span><span class="re1">$hash</span> <span class="sy0">.</span> <span class="re1">$password</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="sy0">&#8211;</span><span class="re1">$count</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">=</span> <span class="kw3">substr</span><span class="br0">&#40;</span><span class="re1">$setting</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">12</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$output</span> <span class="sy0">.=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_hash_encode64<span class="br0">&#40;</span><span class="re1">$hash</span><span class="sy0">,</span> <span class="nu0">16</span><span class="sy0">,</span> <span class="re1">$itoa64</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$output</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Few comments:</p>
<ol>
<li>The above code is taken directly from the phpBB codebase, I only made a couple of necessary changes to make it work with Zend Framework.</li>
<li>For those of you asking why didn&#8217;t I just use phpBB API and call its native functions, there is a reason for it. The phpBB code is written to be available with PHP 4. Zend Framework requires at least PHP 5.2.4. There are lots of globals and other scary stuff in the phpBB codebase which makes it impossible for its functions to be called from ZF controllers.</li>
<li>If you think I should have done something differently or I completely forgot to do something, please let me know.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2010/05/how-to-register-a-new-phpbb-user-with-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Simple Search Engine Implementing Zend_Search_Lucene</title>
		<link>http://blog.richardknop.com/2010/03/a-simple-search-engine-implementing-zend_search_lucene/</link>
		<comments>http://blog.richardknop.com/2010/03/a-simple-search-engine-implementing-zend_search_lucene/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 15:51:36 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Search_Lucene]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=555</guid>
		<description><![CDATA[Zend_Search_Lucene is a PHP port of a popular Java search engine Apache Lucene. It is also an important part of Zend Framework. Some say that it is too sluggish to be used in robust web applications and recommend faster alternatives such as Sphinx but that is not today&#8217;s topic. In this post I will show [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://framework.zend.com/manual/en/zend.search.lucene.html">Zend_Search_Lucene</a> is a PHP port of a popular Java search engine <a href="http://lucene.apache.org/java/docs/">Apache Lucene</a>. It is also an important part of Zend Framework. Some say that it is too sluggish to be used in robust web applications and recommend faster alternatives such as <a href="http://www.sphinxsearch.com/">Sphinx</a> but that is not today&#8217;s topic. In this post I will show you a basic implementation of Zend_Search_Lucene that has worked well so far for medium websites I have worked on. There are two main tasks you will have to take care of:</p>
<ol>
<li>Creating an index and updating it regularly.</li>
<li>Searching the index with a powerful <a href="http://framework.zend.com/manual/en/zend.search.lucene.query-language.html">query language</a>.</li>
</ol>
<p>First, let&#8217;s create a fresh search index. I know it&#8217;s already tiresome but I will use a simple blog application for my example implementation. To simplify it even further, it will only be possible to search blog posts. The posts schema looks like this:</p>
<pre>CREATE TABLE posts (
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
body TEXT NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
user_id INT NOT NULL,
INDEX (created_at),
INDEX (user_id),
FOREIGN KEY (user_id)
REFERENCES users(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
PRIMARY KEY (id)
) ENGINE = INNODB;</pre>
<p>Creating the search index is easy:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1">Zend_Search_Lucene<span class="sy0">::</span><span class="me2">setDefaultSearchField</span><span class="br0">&#40;</span><span class="st0">&#39;contents&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// create blog posts index located in /data/posts_index</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// make sure the folder is writable</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$index</span> <span class="sy0">=</span> Zend_Search_Lucene<span class="sy0">::</span><span class="me2">create</span><span class="br0">&#40;</span><span class="st0">&#39;data/posts_index&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// $this-&gt;_getTable() is a method that returns a model</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// get() method of the model returns all posts from the database</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$posts</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getTable<span class="br0">&#40;</span><span class="st0">&#39;Posts&#39;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// iterate through posts and build the index</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re1">$posts</span> <span class="kw1">as</span> <span class="re1">$p</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$doc</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Search_Lucene_Document<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$doc</span><span class="sy0">-&gt;</span><span class="me1">addField</span><span class="br0">&#40;</span>Zend_Search_Lucene_Field<span class="sy0">::</span><span class="me2">UnIndexed</span><span class="br0">&#40;</span><span class="st0">&#39;entry_id&#39;</span><span class="sy0">,</span> <span class="re1">$p</span><span class="sy0">-&gt;</span><span class="me1">id</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$doc</span><span class="sy0">-&gt;</span><span class="me1">addField</span><span class="br0">&#40;</span>Zend_Search_Lucene_Field<span class="sy0">::</span><span class="me2">Keyword</span><span class="br0">&#40;</span><span class="st0">&#39;title&#39;</span><span class="sy0">,</span> <span class="re1">$p</span><span class="sy0">-&gt;</span><span class="me1">title</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$doc</span><span class="sy0">-&gt;</span><span class="me1">addField</span><span class="br0">&#40;</span>Zend_Search_Lucene_Field<span class="sy0">::</span><span class="me2">UnStored</span><span class="br0">&#40;</span><span class="st0">&#39;contents&#39;</span><span class="sy0">,</span> <span class="re1">$p</span><span class="sy0">-&gt;</span><span class="me1">body</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$index</span><span class="sy0">-&gt;</span><span class="me1">addDocument</span><span class="br0">&#40;</span><span class="re1">$doc</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// commit the index</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$index</span><span class="sy0">-&gt;</span><span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>Pretty straightforward. You can see I have used three different static methods for adding fields to the document:</p>
<ul>
<li><strong>UnIndexed</strong>: unindexed and unstored (therefor unsearchable) but they are returned with search results. Unindexed fields usually store primary keys, timestamps or file paths.</li>
<li><strong>Text</strong>: indexed, stored and tokenized. Text fields are searchable and are returned with search hits. Titles, first and last names, cities and states, post codes and street names are all good candidates for keyword fields.</li>
<li><strong>UnStored</strong>: indexed and unstored &#8211; ideal for large texts.</li>
</ul>
<p>There are more types of fields you can use (keyword, binary) but you can read about them in the documentation.</p>
<p>Next thing you need to do is update the index every once in a while so the search hits return up-to-date information. There are two ways to get around this problem. The most obvious is to update the index every time a new post is published or an existing post is edited. Another approach would be to set up a cron job to run every now and then and rebuild the index. Which way you choose depends on many variables such as expected index size (a very large index can have few GBs in size).</p>
<p>Secondly, the index is already taken care of, so let&#8217;s search it:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1">Zend_Search_Lucene_Analysis_Analyzer<span class="sy0">::</span><span class="me2">setDefault</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">Zend_Search_Lucene<span class="sy0">::</span><span class="me2">setResultSetLimit</span><span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// explode the search query to individual words</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$words</span>  <span class="sy0">=</span> <span class="kw3">explode</span><span class="br0">&#40;</span><span class="st0">&#39; &#39;</span><span class="sy0">,</span> <span class="kw3">urldecode</span><span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getParam</span><span class="br0">&#40;</span><span class="st0">&#39;search_for&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// start a search query and add a term for each word to it</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$query</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Search_Lucene_Search_Query_MultiTerm<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re1">$words</span> <span class="kw1">as</span> <span class="re1">$w</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$query</span><span class="sy0">-&gt;</span><span class="me1">addTerm</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Search_Lucene_Index_Term<span class="br0">&#40;</span><span class="re1">$w</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// open and query the index</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$index</span> <span class="sy0">=</span> Zend_Search_Lucene<span class="sy0">::</span><span class="me2">open</span><span class="br0">&#40;</span><span class="st0">&#39;data/posts_index&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$results</span> <span class="sy0">=</span> <span class="re1">$index</span><span class="sy0">-&gt;</span><span class="me1">find</span><span class="br0">&#40;</span><span class="re1">$query</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// the search results</span></div>
</li>
</ol>
</div>
<p>That was possibly the simplest possible example of a Lucene search query. You can, however, create very complex queries with the powerful Lucene query language. You can either build queries manually in PHP or you can use Zend_Search_Lucene methods to build them. It&#8217;s so easy a baby could do it.</p>
<p>To search for posts with words &#8216;hello&#8217; and &#8216;word&#8217; in the contents field you would write this query:</p>
<pre>hello</pre>
<p>To search for a post that must contain &#8216;hello&#8217; and may contain &#8216;world&#8217;:</p>
<pre>+hello world</pre>
<p>To search for a post that must contain &#8216;hello&#8217; in the contents field and may contain &#8216;world&#8217; in the title field:</p>
<pre>+hello title:"world"</pre>
<p>And those were just basics. You can use boolean operators, wildcards, ranges and even perform a fuzzy search.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2010/03/a-simple-search-engine-implementing-zend_search_lucene/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caching with Zend_Cache</title>
		<link>http://blog.richardknop.com/2009/12/caching-with-zend_cache/</link>
		<comments>http://blog.richardknop.com/2009/12/caching-with-zend_cache/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 14:21:42 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=523</guid>
		<description><![CDATA[Caching with PHP is the best way to speed up your application and it&#8217;s quite easy thanks to native PHP modules such as APC or output buffering control. It&#8217;s even much much easier when you are using the Zend Framework as it contains a native class just for caching &#8211; Zend_Cache. To use the Zend_Cache [...]]]></description>
			<content:encoded><![CDATA[<p>Caching with PHP is the best way to speed up your application and it&#8217;s quite easy thanks to native PHP modules such as <a href="http://php.net/manual/en/book.apc.php">APC</a> or <a href="http://php.net/manual/en/book.outcontrol.php">output buffering control</a>. It&#8217;s even much much easier when you are using the Zend Framework as it contains a native class just for caching &#8211; <a href="http://framework.zend.com/manual/en/zend.cache.html">Zend_Cache</a>. To use the Zend_Cache you must first initialize it in the bootstrap and add it to the registry so you can access it easily in controllers, I do it like this:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1">protected <span class="kw2">function</span> _initCache<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$frontend</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;lifetime&#39;</span> <span class="sy0">=&gt;</span> <span class="nu0">7200</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;automatic_seralization&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// where are we going to stored the cached files?</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$backend</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;cache_dir&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;cache&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">cache</span> <span class="sy0">=</span> Zend_Cache<span class="sy0">::</span><span class="me2">factory</span><span class="br0">&#40;</span><span class="st0">&#39;core&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;File&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$frontend</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$backend</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">protected <span class="kw2">function</span> _initRegistry<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">registry</span> <span class="sy0">=</span> Zend_Registry<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">registry</span><span class="sy0">-&gt;</span><span class="me1">cache</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">cache</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// I store much more in the registry, of course</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// for instance, configuration and db adapter</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>The frontend and the backend adapters can take much more arguments, read the documentation to learn all possible options. I initialized the Zend_Cache object with the factory method. First argument means that we want to use the Zend_Cache_Core frontend which is the core of the Zend_Cache module. The second argument is the backend we want to use the Zend_Cache_Backend_File backend or that we want to store cached data as files in a specific directory. The other two parameters are frontend and backend options.</p>
<p>Now we can easily access the cache object in controllers or models:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="re1">$cache</span> <span class="sy0">=</span> Zend_Registry<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st0">&#39;cache&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// does the cache contain data we are looking for?</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re1">$result</span> <span class="sy0">=</span> <span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">load</span><span class="br0">&#40;</span><span class="st0">&#39;myUniqueId&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// if not let&#39;s cache the data</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// here I use only a random array but in a real application</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// you would probably cache some database entries</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$data</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;John Doe&#39;</span><span class="sy0">,</span> <span class="st0">&#39;Jane Doe&#39;</span><span class="sy0">,</span> <span class="st0">&#39;Baby Doe&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// besides unique cache id you can use tags to categorize data</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">save</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="sy0">,</span> <span class="st0">&#39;myUniqueId&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag1&#39;</span><span class="sy0">,</span> <span class="st0">&#39;tag2&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// dump the cached data</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">var_dump</span><span class="br0">&#40;</span><span class="re1">$result</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>That was easy, wasn&#8217;t it?</p>
<h3>Cleaning the cache</h3>
<p>You will surely also want to remove cached files at some point in your application:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// clean all cached files</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">clean</span><span class="br0">&#40;</span>Zend_Cache<span class="sy0">::</span> <span class="me2">CLEANING_MODE_ALL</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// clean only outdated cached files</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">clean</span><span class="br0">&#40;</span>Zend_Cache<span class="sy0">::</span><span class="me2">CLEANING_MODE_OLD</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// remove a particular cache id</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st0">&#39;myUniqueId&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// remove records tagged as &quot;tag1&quot; AND &quot;tag2&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">clean</span><span class="br0">&#40;</span>Zend_Cache<span class="sy0">::</span><span class="me2">CLEANING_MODE_MATCHING_TAG</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag1&#39;</span><span class="sy0">,</span> <span class="st0">&#39;tag2&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// remove records tagged as &quot;tag1&quot; OR :tag2&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">clean</span><span class="br0">&#40;</span>Zend_Cache<span class="sy0">::</span><span class="me2">CLEANING_MODE_MATCHING_ANY_TAG</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag1&#39;</span><span class="sy0">,</span> <span class="st0">&#39;tag2&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// remove records NOT tagged as &quot;tag1&quot; or &quot;tag2&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$cache</span><span class="sy0">-&gt;</span><span class="me1">clean</span><span class="br0">&#40;</span>Zend_Cache<span class="sy0">::</span><span class="me2">CLEANING_MODE_NOT_MATCHING_ANY_TAG</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag1&#39;</span><span class="sy0">,</span> <span class="st0">&#39;tag2&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>That&#8217;s it for today and, by the way, Merry Christmas <img src='http://blog.richardknop.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/12/caching-with-zend_cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQLSTATE[42000]: Syntax error or access violation: 1064</title>
		<link>http://blog.richardknop.com/2009/10/sqlstate42000-syntax-error-or-access-violation-1064/</link>
		<comments>http://blog.richardknop.com/2009/10/sqlstate42000-syntax-error-or-access-violation-1064/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 22:16:28 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=465</guid>
		<description><![CDATA[If you are using PDO adapter to work with databases in Zend Framework you might come across an exception similar to this: Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near [...]]]></description>
			<content:encoded><![CDATA[<p>If you are using PDO adapter to work with databases in Zend Framework you might come across an exception similar to this:</p>
<pre>Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 2</pre>
<p>It took me some time to track down the cause of this error message. I was building a complex query with <a href="http://framework.zend.com/manual/en/zend.db.select.html">Zend_Db_Select</a> which included several joins and subqueries so I thought I had made a mistake in syntax somewhere but the problem was I was passing an undefined variable to where() method. So the problematic line was:</p>
<pre>$select-&gt;where($where);</pre>
<p>And $where was not defined. Hope this helps somebody.</p>
<h3>Addendum (<span id="timestamp"><strong>Oct 6, 2009 @ 14:13</strong></span>)</h3>
<p>The same problem can occur also when there is any error in your WHERE clause, for instance:</p>
<pre>WHERE id =</pre>
<p>The above (there&#8217;s a missing integer after &#8220;id =&#8221;) would throw the same exception.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/10/sqlstate42000-syntax-error-or-access-violation-1064/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>#1005 &#8211; Can&#8217;t create table &#8216;database_name.table_name&#8217; (errno: 150)</title>
		<link>http://blog.richardknop.com/2009/07/1005-cant-create-table-database_name-table_name-errno-150/</link>
		<comments>http://blog.richardknop.com/2009/07/1005-cant-create-table-database_name-table_name-errno-150/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 22:20:40 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Foreign keys]]></category>
		<category><![CDATA[InnoDB]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=444</guid>
		<description><![CDATA[When you are working with MySQL InnoDB table engine and especially foreign keys (as I do) you will encounter a similar error message quite often. Tracking down where exactly lies the problem can be very frustrating as the error message isn&#8217;t very suggestive. From my experience, the problem is 99% of the time with foreign [...]]]></description>
			<content:encoded><![CDATA[<p>When you are working with MySQL InnoDB table engine and especially foreign keys (as I do) you will encounter a similar error message quite often. Tracking down where exactly lies the problem can be very frustrating as the error message isn&#8217;t very suggestive.</p>
<p>From my experience, the problem is 99% of the time with foreign keys. Here are three most common reasons I have come across:</p>
<ul>
<li>the two fields in the foreign key relationship are not exactly the same type (for example one is TEXT and another is VARCHAR)</li>
<li>although the two fields are the same type they aren&#8217;t the same size (for example one is INT(10) and another is INT(4))</li>
<li>the field you are referencing with the foreign key has no index (if the field is not a primary key you must add index to it)</li>
</ul>
<p>I hope this might be helpfull to someone who comes across a similar error message.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/07/1005-cant-create-table-database_name-table_name-errno-150/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>User login and authentication with Zend_Auth and Zend_Acl</title>
		<link>http://blog.richardknop.com/2009/06/user-login-and-authentication-with-zend_auth-and-zend_acl/</link>
		<comments>http://blog.richardknop.com/2009/06/user-login-and-authentication-with-zend_auth-and-zend_acl/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 20:43:00 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Hashes and salts]]></category>
		<category><![CDATA[Login and authentication]]></category>
		<category><![CDATA[Zend_Acl]]></category>
		<category><![CDATA[Zend_Auth]]></category>
		<category><![CDATA[Zend_Form]]></category>
		<category><![CDATA[Zend_Mail]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=369</guid>
		<description><![CDATA[Whether you are working on a content management system or almost any other type of application with member or admin area, user login and authentication is one of the most important tasks you will encounter. In this post I will show you how to combine Zend_Auth and Zend_Acl to create a flexible user system with [...]]]></description>
			<content:encoded><![CDATA[<p>Whether you are working on a content management system or almost any other type of application with member or admin area, user login and authentication is one of the most important tasks you will encounter. In this post I will show you how to combine <a href="http://framework.zend.com/manual/en/zend.auth.html">Zend_Auth</a> and <a href="http://framework.zend.com/manual/en/zend.acl.html">Zend_Acl</a> to create a flexible user system with different access levels.</p>
<p>Scenario is simple. Your application has three modules and each module needs to be accessible to users with different priviledges:</p>
<ol>
<li>&#8216;default&#8217; module &#8211; accessible to all users and guests</li>
<li>&#8216;member&#8217; module &#8211; accessible only to registered users</li>
<li>&#8216;admin&#8217; module &#8211; accessible only to registered users with administrator priviledges</li>
</ol>
<p>I will go step by step and explain all parts in depth:</p>
<ul>
<li>database table and model</li>
<li>registration form</li>
<li>registration controller action</li>
<li>login form</li>
<li>login controller action</li>
<li>logout controller action</li>
<li>authentication controller plugin</li>
<li>recommended reading</li>
</ul>
<h2>Database table and model</h2>
<p>Let&#8217;s create a database table that will store all users:</p>
<pre>CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
username VARCHAR(255) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(255) NOT NULL,
status VARCHAR(255) NOT NULL,
INDEX (first_name),
INDEX (last_name),
INDEX (username),
INDEX (email),
PRIMARY KEY (id)
) ENGINE = INNODB;</pre>
<p>The &#8216;role&#8217; column will hold a user access level, for example: &#8216;user&#8217;, &#8216;administrator&#8217; etc. The &#8216;status&#8217; column could have &#8216;pending&#8217; and &#8216;approved&#8217; possible values which would allow administrators to approve freshly registered users before they could access private parts of the website.</p>
<p>I put INDEX on &#8216;first_name&#8217;, &#8216;last_name&#8217;, &#8216;username&#8217; and &#8216;email&#8217; fields because are often be used instead of the &#8216;id&#8217; to fetch a single user.</p>
<p>You will also need a model representing the table. Here is a very simple model, in a real-life application you will certainly need more methods (for editing and removing users etc):</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Users <span class="kw2">extends</span> Zend_Db_Table_Abstract</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> add<span class="br0">&#40;</span><span class="kw3">array</span> <span class="re1">$data</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password_hash&#39;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;salt&#39;</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="kw3">sha1</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;salt&#39;</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">unset</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;salt&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">insert</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> getSingleWithUsername<span class="br0">&#40;</span><span class="re1">$username</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">select</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$where</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getAdapter</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">quoteInto</span><span class="br0">&#40;</span><span class="st0">&#39;username = ?&#39;</span><span class="sy0">,</span> <span class="re1">$username</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span><span class="sy0">-&gt;</span><span class="me1">where</span><span class="br0">&#40;</span><span class="re1">$where</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">fetchRow</span><span class="br0">&#40;</span><span class="re1">$select</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> getSingleWithEmail<span class="br0">&#40;</span><span class="re1">$email</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">select</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$where</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getAdapter</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">quoteInto</span><span class="br0">&#40;</span><span class="st0">&#39;email = ?&#39;</span><span class="sy0">,</span> <span class="re1">$email</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span><span class="sy0">-&gt;</span><span class="me1">where</span><span class="br0">&#40;</span><span class="re1">$where</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">fetchRow</span><span class="br0">&#40;</span><span class="re1">$select</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> getSingleWithEmailHash<span class="br0">&#40;</span><span class="re1">$hash</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">select</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$where</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getAdapter</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">quoteInto</span><span class="br0">&#40;</span><span class="st0">&#39;SHA1(email) = ?&#39;</span><span class="sy0">,</span> <span class="re1">$hash</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span><span class="sy0">-&gt;</span><span class="me1">where</span><span class="br0">&#40;</span><span class="re1">$where</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">fetchRow</span><span class="br0">&#40;</span><span class="re1">$select</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Notice this line in the add() method:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password_hash&#39;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;salt&#39;</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="kw3">sha1</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;salt&#39;</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>What it does is it first prepends the salt to the plain text password and then create an sha1 hash which can be safely stored in the database.</p>
<h2>Registration form</h2>
<p>Unless you want to create user accounts manually you should allow guests to register. The registration form:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Register <span class="kw2">extends</span> Zend_Form</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="re1">$elementDecorators</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;ViewHelper&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;data&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;div&#39;</span><span class="sy0">,</span> <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;element&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;Label&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;row&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;li&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="re1">$buttonDecorators</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;ViewHelper&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;data&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;div&#39;</span><span class="sy0">,</span> <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;button&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;row&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;li&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> init<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">setMethod</span><span class="br0">&#40;</span><span class="st0">&#39;post&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$firstName</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Text<span class="br0">&#40;</span><span class="st0">&#39;first_name&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;First name&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-text&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$lastName</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Text<span class="br0">&#40;</span><span class="st0">&#39;last_name&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;First name&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-text&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$email</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Text<span class="br0">&#40;</span><span class="st0">&#39;email&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Email&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;EmailAddress&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-text&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$emailAgain</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Text<span class="br0">&#40;</span><span class="st0">&#39;emailAgain&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Email again&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;EmailAddress&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-text&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$username</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Text<span class="br0">&#40;</span><span class="st0">&#39;username&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Username&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">3</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-text&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$password</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Password<span class="br0">&#40;</span><span class="st0">&#39;password&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Password&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">6</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-password&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$passwordAgain</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Password<span class="br0">&#40;</span><span class="st0">&#39;passwordAgain&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Password again&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">6</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-password&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$submit</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Submit<span class="br0">&#40;</span><span class="st0">&#39;register&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">buttonDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Register&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-submit&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">addElements</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$firstName</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$lastName</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$email</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$emailAgain</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$username</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$password</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$passwordAgain</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$submit</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> loadDefaultDecorators<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">setDecorators</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;FormErrors&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;FormElements&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;HtmlTag&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;ol&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;Form&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>The form is straightforward &#8211; a single form element per table column (except &#8216;id&#8217;, &#8216;role&#8217; and &#8216;status&#8217;). I always use my custom decorators which produce the markup I want.</p>
<h2>Registration controller action</h2>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> registerAction<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// redirect logged in users</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Zend_Registry<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&#39;auth&#39;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">hasIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_redirect<span class="br0">&#40;</span><span class="st0">&#39;/&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$request</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getRequest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$users</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getTable<span class="br0">&#40;</span><span class="st0">&#39;Users&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$form</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getForm<span class="br0">&#40;</span><span class="st0">&#39;Register&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_helper<span class="sy0">-&gt;</span><span class="me1">url</span><span class="br0">&#40;</span><span class="st0">&#39;register&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// if POST data has been submitted</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">isPost</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the Register form has been submitted and the submitted data is valid</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;register&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">isValid</span><span class="br0">&#40;</span><span class="re1">$_POST</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$data</span> <span class="sy0">=</span> <span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">getValues</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$users</span><span class="sy0">-&gt;</span><span class="me1">getSingleWithEmail</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the email already exists in the database</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Email already taken&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$users</span><span class="sy0">-&gt;</span><span class="me1">getSingleWithUsername</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the username already exists in the database</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Username already taken&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span> <span class="sy0">!=</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;emailAgain&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if both emails do not match</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Both emails must be same&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span> <span class="sy0">!=</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;passwordAgain&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if both passwords do not match</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Both passwords must be same&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// everything is OK, let&#39;s send email with a verification string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// the verifications string is an sha1 hash of the email</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$mail</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Mail<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$mail</span><span class="sy0">-&gt;</span><span class="me1">setFrom</span><span class="br0">&#40;</span><span class="st0">&#39;your@name.com&#39;</span><span class="sy0">,</span> <span class="st0">&#39;Your Name&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$mail</span><span class="sy0">-&gt;</span><span class="me1">setSubject</span><span class="br0">&#40;</span><span class="st0">&#39;Thank you for registering&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$mail</span><span class="sy0">-&gt;</span><span class="me1">setBodyText</span><span class="br0">&#40;</span><span class="st0">&#39;Dear Sir or Madam,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">Thank You for registering at yourwebsite.com. In order for your account to be</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">activated please click on the following URI:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="st0">http://yourwebsite.com/admin/login/email-verification?str=&#39;</span> <span class="sy0">.</span> <span class="kw3">sha1</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">.</span> <span class="st0">&#39;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">Best Regards,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">Your Name and yourwebsite.com staff&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$mail</span><span class="sy0">-&gt;</span><span class="me1">addTo</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;email&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;first_name&#39;</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st0">&#39; &#39;</span> <span class="sy0">.</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;last_name&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re1">$mail</span><span class="sy0">-&gt;</span><span class="me1">send</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// email sending failed</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Failed to send email to the address you provided&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// email sent successfully, let&#39;s add the user to the database</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">unset</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;emailAgain&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;passwordAgain&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;register&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;salt&#39;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_helper<span class="sy0">-&gt;</span><span class="me1">RandomString</span><span class="br0">&#40;</span><span class="nu0">40</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;role&#39;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st0">&#39;user&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$data</span><span class="br0">&#91;</span><span class="st0">&#39;status&#39;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st0">&#39;pending&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$users</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="re1">$data</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">success</span> <span class="sy0">=</span> <span class="st0">&#39;Successfully registered&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">form</span> <span class="sy0">=</span> <span class="re1">$form</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>First of all, in order to eliminate duplicate rows in the database we check for users with the same username or email before continuing. We also make sure a user correctly filled in both email input fields and both password input fields.</p>
<p>Afterwards, an email with a verification string (which happens to be an sha1 hash of the user email) is sent to the user and a new account is created. I use a handy action helper to generate a random string (in this case used as a salt):</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> My_Controller_Action_Helper_RandomString <span class="kw2">extends</span> Zend_Controller_Action_Helper_Abstract</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> direct<span class="br0">&#40;</span><span class="re1">$length</span> <span class="sy0">=</span> <span class="nu0">32</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re1">$chars</span> <span class="sy0">=</span> <span class="st0">&#39;1234567890abcdef&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// length of character list</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$charsLength</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$chars</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// start our string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$string</span> <span class="sy0">=</span> <span class="re1">$chars</span><span class="br0">&#123;</span><span class="kw3">rand</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="re1">$charsLength</span><span class="br0">&#41;</span><span class="br0">&#125;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// generate random string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> <span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$length</span><span class="sy0">;</span> <span class="re1">$i</span> <span class="sy0">=</span> <span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$string</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// grab a random character from our list</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$r</span> <span class="sy0">=</span> <span class="re1">$chars</span><span class="br0">&#123;</span><span class="kw3">rand</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="re1">$charsLength</span><span class="br0">&#41;</span><span class="br0">&#125;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// make sure the same two characters don&#39;t appear next to each other</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$r</span> <span class="sy0">!=</span> <span class="re1">$string</span><span class="br0">&#123;</span><span class="re1">$i</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#125;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$string</span> <span class="sy0">.=</span> &nbsp;<span class="re1">$r</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$i</span><span class="sy0">&#8211;;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// return the string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$string</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>By clicking on the link the user is taken to the email verification page:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> emailVerificationAction<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$request</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getRequest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$users</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getTable<span class="br0">&#40;</span><span class="st0">&#39;Users&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// get the verification string from the URI</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$str</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getParam</span><span class="br0">&#40;</span><span class="st0">&#39;str&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// check if the user corresponding to the string exists</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$user</span> <span class="sy0">=</span> <span class="re1">$users</span><span class="sy0">-&gt;</span><span class="me1">getSingleWithEmailHash</span><span class="br0">&#40;</span><span class="re1">$str</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$user</span> <span class="sy0">==</span> <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Invalid verification string&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">status</span> <span class="sy0">==</span> <span class="st0">&#39;approved&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// user account has already been activated</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Account has already been activated&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// the user exists and the verification string is correct</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// let&#39;s approve the user</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$users</span><span class="sy0">-&gt;</span><span class="me1">edit</span><span class="br0">&#40;</span><span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">id</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;status&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;approved&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">success</span> <span class="sy0">=</span> <span class="st0">&#39;Hello, &#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">.</span> <span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">username</span> <span class="sy0">.</span> <span class="st0">&#39;! Your account has been activated&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h2>Login form</h2>
<p>The login form is quite simple. It contains just two input fields (for username and password) and a &#8220;Remember me?&#8221; checkbox:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Login <span class="kw2">extends</span> Zend_Form</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="re1">$elementDecorators</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;ViewHelper&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;data&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;div&#39;</span><span class="sy0">,</span> <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;element&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;Label&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;row&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;li&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="re1">$buttonDecorators</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;ViewHelper&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;data&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;div&#39;</span><span class="sy0">,</span> <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;button&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;row&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;li&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="re1">$checkboxDecorators</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;Label&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;ViewHelper&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;data&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;div&#39;</span><span class="sy0">,</span> <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;checkbox&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;row&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;HtmlTag&#39;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;li&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> init<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">setMethod</span><span class="br0">&#40;</span><span class="st0">&#39;post&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$username</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Text<span class="br0">&#40;</span><span class="st0">&#39;username&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Username&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">3</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-text&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$password</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Password<span class="br0">&#40;</span><span class="st0">&#39;password&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">elementDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Password&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;filters&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;StringTrim&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;validators&#39;</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;StringLength&#39;</span><span class="sy0">,</span> <span class="kw2">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">6</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-password&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$rememberMe</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Checkbox<span class="br0">&#40;</span><span class="st0">&#39;rememberMe&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">checkboxDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Remember me?&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;required&#39;</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-checkbox&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$submit</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Form_Element_Submit<span class="br0">&#40;</span><span class="st0">&#39;login&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;decorators&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">buttonDecorators</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;label&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;Login&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;class&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;input-submit&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">addElements</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$username</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$password</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$rememberMe</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$submit</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> loadDefaultDecorators<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">setDecorators</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;FormErrors&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;FormElements&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;HtmlTag&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;tag&#39;</span> <span class="sy0">=&gt;</span> <span class="st0">&#39;ol&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;Form&#39;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h2>Login controller action</h2>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> indexAction<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// redirect logged in users</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Zend_Registry<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&#39;auth&#39;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">hasIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_redirect<span class="br0">&#40;</span><span class="st0">&#39;/&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$request</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getRequest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$users</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getTable<span class="br0">&#40;</span><span class="st0">&#39;Users&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$form</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getForm<span class="br0">&#40;</span><span class="st0">&#39;Login&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_helper<span class="sy0">-&gt;</span><span class="me1">url</span><span class="br0">&#40;</span><span class="st0">&#39;login&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// if POST data has been submitted</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">isPost</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the Login form has been submitted and the submitted data is valid</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;login&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">isValid</span><span class="br0">&#40;</span><span class="re1">$_POST</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// prepare a database adapter for Zend_Auth</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Auth_Adapter_DbTable<span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span>_getDb<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setTableName</span><span class="br0">&#40;</span><span class="st0">&#39;users&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setIdentityColumn</span><span class="br0">&#40;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setCredentialColumn</span><span class="br0">&#40;</span><span class="st0">&#39;password_hash&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setCredentialTreatment</span><span class="br0">&#40;</span><span class="st0">&#39;CONCAT(SUBSTRING(password_hash, 1, 40), SHA1(CONCAT(SUBSTRING(password_hash, 1, 40), ?)))&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setIdentity</span><span class="br0">&#40;</span><span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">getValue</span><span class="br0">&#40;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setCredential</span><span class="br0">&#40;</span><span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">getValue</span><span class="br0">&#40;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// try to authenticate a user</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$auth</span> <span class="sy0">=</span> Zend_Registry<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st0">&#39;auth&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$result</span> <span class="sy0">=</span> <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">authenticate</span><span class="br0">&#40;</span><span class="re1">$adapter</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// is the user valid one?</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span><span class="re1">$result</span><span class="sy0">-&gt;</span><span class="me1">getCode</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> Zend_Auth_Result<span class="sy0">::</span><span class="me2">FAILURE_IDENTITY_NOT_FOUND</span><span class="sy0">:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Identity not found&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> Zend_Auth_Result<span class="sy0">::</span><span class="me2">FAILURE_CREDENTIAL_INVALID</span><span class="sy0">:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Invalid credential&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> Zend_Auth_Result<span class="sy0">::</span><span class="me2">SUCCESS</span><span class="sy0">:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// get user object (ommit password_hash)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$user</span> <span class="sy0">=</span> <span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">getResultRowObject</span><span class="br0">&#40;</span><span class="kw2">null</span><span class="sy0">,</span> <span class="st0">&#39;password_hash&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// check if the user is approved</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">status</span> <span class="sy0">!=</span> <span class="st0">&#39;approved&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;User not approved&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// to help thwart session fixation/hijacking</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$form</span><span class="sy0">-&gt;</span><span class="me1">getValue</span><span class="br0">&#40;</span><span class="st0">&#39;rememberMe&#39;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// remember the session for 604800s = 7 days</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Zend_Session<span class="sy0">::</span><span class="me2">rememberMe</span><span class="br0">&#40;</span><span class="nu0">604800</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// do not remember the session</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Zend_Session<span class="sy0">::</span><span class="me2">forgetMe</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// store user object in the session</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$authStorage</span> <span class="sy0">=</span> <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getStorage</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$authStorage</span><span class="sy0">-&gt;</span><span class="me1">write</span><span class="br0">&#40;</span><span class="re1">$user</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_redirect<span class="br0">&#40;</span><span class="st0">&#39;/admin&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">default</span><span class="sy0">:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">error</span> <span class="sy0">=</span> <span class="st0">&#39;Wrong username and/or password&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">form</span> <span class="sy0">=</span> <span class="re1">$form</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Notice this line:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="re1">$adapter</span><span class="sy0">-&gt;</span><span class="me1">setCredentialTreatment</span><span class="br0">&#40;</span><span class="st0">&#39;CONCAT(SUBSTRING(password_hash, 1, 40), SHA1(CONCAT(SUBSTRING(password_hash, 1, 40), ?)))&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>The argument of the setCredentialTreatment() method is probably confusing, it&#8217;s a little more complex  SQL expression. What it does is it compares the entered password with the password_hash from the database (substitute the entered password for the question mark). CONCAT() is a MySQL function for concating strings (in PHP it&#8217;s done with the concatenation operator &#8211; &#8216;.&#8217;), SUBSTRING() is very similar to the PHP&#8217;s substr() (the only difference is the first character has index 1 in MySQL and 0 in PHP), SHA1() is the same as sha1() in PHP.</p>
<h2>Logout controller action</h2>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> logoutAction<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; Zend_Registry<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st0">&#39;auth&#39;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">clearIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_redirect<span class="br0">&#40;</span><span class="st0">&#39;/&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h2>Authentication controller plugin</h2>
<p>I always use a controller plugin for authentication. You could possibly do it in controllers (let&#8217;s say in the init() method) but I find the controller plugin to be an ideal for this purpose:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> My_Controller_Plugin_Auth <span class="kw2">extends</span> Zend_Controller_Plugin_Abstract</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> preDispatch<span class="br0">&#40;</span>Zend_Controller_Request_Abstract <span class="re1">$request</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$auth</span> <span class="sy0">=</span> Zend_Registry<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&#39;auth&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Acl<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// for default module</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getModuleName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="st0">&#39;default&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access resources (controllers)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// usually there will be more access resources</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Resource<span class="br0">&#40;</span><span class="st0">&#39;index&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Resource<span class="br0">&#40;</span><span class="st0">&#39;error&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access roles</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;guest&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access rules</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;guest&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// allow guests everywhere</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// allow users everywhere</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// allow administrators everywhere</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$role</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">status</span> <span class="sy0">=</span> <span class="st0">&#39;approved&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ? <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">role</span> <span class="sy0">:</span> <span class="st0">&#39;guest&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$controller</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getControllerName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$action</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getActionName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">isAllowed</span><span class="br0">&#40;</span><span class="re1">$role</span><span class="sy0">,</span> <span class="re1">$controller</span><span class="sy0">,</span> <span class="re1">$action</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$redirector</span> <span class="sy0">=</span> Zend_Controller_Action_HelperBroker<span class="sy0">::</span><span class="me2">getStaticHelper</span><span class="br0">&#40;</span><span class="st0">&#39;Redirector&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$redirector</span><span class="sy0">-&gt;</span><span class="me1">gotoUrlAndExit</span><span class="br0">&#40;</span><span class="st0">&#39;error/denied&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// for member module</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getModuleName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="st0">&#39;member&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access resources (controllers)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// usually there will be more access resources</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Resource<span class="br0">&#40;</span><span class="st0">&#39;index&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Resource<span class="br0">&#40;</span><span class="st0">&#39;error&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access roles</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;guest&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access rules</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// allow users everywhere</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// allow administrators everywhere</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$role</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">status</span> <span class="sy0">=</span> <span class="st0">&#39;approved&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ? <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">role</span> <span class="sy0">:</span> <span class="st0">&#39;guest&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$controller</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getControllerName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$action</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getActionName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">isAllowed</span><span class="br0">&#40;</span><span class="re1">$role</span><span class="sy0">,</span> <span class="re1">$controller</span><span class="sy0">,</span> <span class="re1">$action</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$redirector</span> <span class="sy0">=</span> Zend_Controller_Action_HelperBroker<span class="sy0">::</span><span class="me2">getStaticHelper</span><span class="br0">&#40;</span><span class="st0">&#39;Redirector&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$redirector</span><span class="sy0">-&gt;</span><span class="me1">gotoUrlAndExit</span><span class="br0">&#40;</span><span class="st0">&#39;error/denied&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// for admin module</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getModuleName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="st0">&#39;admin&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access resources (controllers)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// usually there will be more access resources</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Resource<span class="br0">&#40;</span><span class="st0">&#39;index&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Resource<span class="br0">&#40;</span><span class="st0">&#39;error&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access roles</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;guest&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">addRole</span><span class="br0">&#40;</span><span class="kw2">new</span> Zend_Acl_Role<span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// access rules</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// allow administrators everywhere</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$role</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">status</span> <span class="sy0">=</span> <span class="st0">&#39;approved&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ? <span class="re1">$auth</span><span class="sy0">-&gt;</span><span class="me1">getIdentity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">role</span> <span class="sy0">:</span> <span class="st0">&#39;guest&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$controller</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getControllerName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$action</span> <span class="sy0">=</span> <span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getActionName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">isAllowed</span><span class="br0">&#40;</span><span class="re1">$role</span><span class="sy0">,</span> <span class="re1">$controller</span><span class="sy0">,</span> <span class="re1">$action</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$redirector</span> <span class="sy0">=</span> Zend_Controller_Action_HelperBroker<span class="sy0">::</span><span class="me2">getStaticHelper</span><span class="br0">&#40;</span><span class="st0">&#39;Redirector&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$redirector</span><span class="sy0">-&gt;</span><span class="me1">gotoUrlAndExit</span><span class="br0">&#40;</span><span class="st0">&#39;error/denied&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>As you can see, there are different access rules for each module. It&#8217;s not terribly difficult to create more comples access rules. The one thing you must understand is that (quoted from the Zend Framework documentation):</p>
<blockquote><p>In general, <code class="classname">Zend_Acl</code> obeys a given rule if and only if a                 more specific rule does not apply.</p></blockquote>
<p>For instance, let&#8217;s say you want to disallow logged in users from accessing the login form:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// allow guest to access the login controller</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// this still doesn&#39;t mean they can access any other controller unless specified</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;guest&#39;</span><span class="sy0">,</span> <span class="st0">&#39;login&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// allow users to access all controllers</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// disallow users from accessing specifically the login controller</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">deny</span><span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="sy0">,</span> <span class="st0">&#39;login&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// allow administrators to access all controllers</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">allow</span><span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// disallow administrators from accessing specifically the login controller</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">deny</span><span class="br0">&#40;</span><span class="st0">&#39;administrator&#39;</span><span class="sy0">,</span> <span class="st0">&#39;login&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>You can also specify actions in the access rules:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// disallow users from accessing action1, action2 and action3 of the index controller</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$acl</span><span class="sy0">-&gt;</span><span class="me1">deny</span><span class="br0">&#40;</span><span class="st0">&#39;user&#39;</span><span class="sy0">,</span> <span class="st0">&#39;index&#39;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;action1&#39;</span><span class="sy0">,</span> <span class="st0">&#39;action2&#39;</span><span class="sy0">,</span> <span class="st0">&#39;action3&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>One more thing, you need to register the plugin so it works. I usually do it in the bootstrap file:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="re1">$frontController</span><span class="sy0">-&gt;</span><span class="me1">registerPlugin</span><span class="br0">&#40;</span><span class="kw2">new</span> My_Controller_Plugin_Auth<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>You need to add the &#8216;My_&#8217; namespace to the application config file, too:</p>
<pre>autoloaderNamespaces[] = "My_"</pre>
<h2>Recommended reading</h2>
<ul>
<li><a href="http://blog.richardknop.com/2009/06/my-favorite-zend_form-decorators-configuration/">My favorite Zend_Form decorators configuration</a></li>
<li><a href="http://blog.richardknop.com/2009/06/extending-zend_form/">Extending Zend_Form</a></li>
<li><a href="http://blog.richardknop.com/2009/06/password-hashes-and-salts/">Password hashes and salts</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/06/user-login-and-authentication-with-zend_auth-and-zend_acl/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Password hashes and salts</title>
		<link>http://blog.richardknop.com/2009/06/password-hashes-and-salts/</link>
		<comments>http://blog.richardknop.com/2009/06/password-hashes-and-salts/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 11:21:46 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Hashes and salts]]></category>
		<category><![CDATA[Login and authentication]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=305</guid>
		<description><![CDATA[One of the biggest mistakes novice programmers do is storing plain text passwords in a database. That is a great security risk easily compared (if not greater) to SQL injection or session hijacking. This security risk is common to all server side languages because it is mainly related to how you store the data in [...]]]></description>
			<content:encoded><![CDATA[<p>One of the biggest mistakes novice programmers do is storing plain text passwords in a database. That is a great security risk easily compared (if not greater) to SQL injection or session hijacking. This security risk is common to all server side languages because it is mainly related to how you store the data in databases. Solution is very easy &#8211; use hashes.</p>
<p>What is a hash? A hash is the result of a one-way mathematical process which creates a unique string. The string is next to impossible to decode in order to recover the original text. This makes it an ideal way of storing sensible data in databases &#8211; especially passwords.</p>
<p>There are many hashing algorithms, most widely used are MD5 (128-bit) and sha1 (160-bit). Researchers found out that MD5 and also SHA1 are less secure than previously thought so if security is your top priority, you should look for some more advanced algorithms (256-bit or 512-bit). But for usual applications SHA1 is still very secure.</p>
<h2>Example: Simple user authorization using sha1 hash</h2>
<p>Let&#8217;s create a simple table for users:</p>
<pre>CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(255) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;</pre>
<p>When user registers, you ought to save only a hash of the password in the database:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="coMULTI">/* Add user to the database */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$username</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$password</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="st0">&#39;root&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pass</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$conn</span> <span class="sy0">=</span> <span class="kw2">new</span> PDO<span class="br0">&#40;</span><span class="st0">&#39;mysql:host=localhost;dbname=test&#39;</span><span class="sy0">,</span> <span class="re1">$user</span><span class="sy0">,</span> <span class="re1">$pass</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="st0">&#39;INSERT INTO users (username, password_hash) VALUES (?, sha1(?))&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$username</span><span class="sy0">,</span> <span class="re1">$password</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>When a user attempts to log in, you just need to compare a hash of the user entered password to the hash stored in the database:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="coMULTI">/* Check user credentials */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$username</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$password</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="st0">&#39;root&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pass</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$conn</span> <span class="sy0">=</span> <span class="kw2">new</span> PDO<span class="br0">&#40;</span><span class="st0">&#39;mysql:host=localhost;dbname=test&#39;</span><span class="sy0">,</span> <span class="re1">$user</span><span class="sy0">,</span> <span class="re1">$pass</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="st0">&#39;SELECT * FROM users WHERE username = ?&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$username</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$user</span> <span class="sy0">!=</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">sha1</span><span class="br0">&#40;</span><span class="re1">$password</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">password_hash</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// user has logged in successfully</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h2>Salt improvement</h2>
<p>Even though storing only hashed passwords in the database is already very safe, there is a weakness which can be exploited. If an attacker gains access to the database, he will be able to say that users with the same password hash must also have the same password. This information would be still useless but the attacker can use the &#8216; brute forcing&#8217; (generate numerous potential password hashes &#8211; either randomly generated or from a dictionary &#8211; and compare them with hashes in the database) to decode user passwords.</p>
<p>Strong passwords (containing letters, numbers and other symbols) are secure even against the &#8216;brute forcing&#8217; attacks but users often like short passwords containing only letters or only letters and numbers. This weakness can be overcome by using a &#8216;salt&#8217;. Salt is a randomly generated string which is prepended to a plain text password before using a hasing algorithm. You need a function for creating a random string:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> randomString<span class="br0">&#40;</span><span class="re1">$length</span> <span class="sy0">=</span> <span class="nu0">32</span><span class="sy0">,</span> <span class="re1">$chars</span> <span class="sy0">=</span> <span class="st0">&#39;1234567890abcdef&#39;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// length of character list</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$charsLength</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$chars</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// start our string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$string</span> <span class="sy0">=</span> <span class="re1">$chars</span><span class="br0">&#123;</span><span class="kw3">rand</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="re1">$charsLength</span><span class="br0">&#41;</span><span class="br0">&#125;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// generate random string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> <span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$length</span><span class="sy0">;</span> <span class="re1">$i</span> <span class="sy0">=</span> <span class="kw3">strlen</span><span class="br0">&#40;</span><span class="re1">$string</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// grab a random character from our list</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$r</span> <span class="sy0">=</span> <span class="re1">$chars</span><span class="br0">&#123;</span><span class="kw3">rand</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="re1">$charsLength</span><span class="br0">&#41;</span><span class="br0">&#125;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// make sure the same two characters don&#39;t appear next to each other</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$r</span> <span class="sy0">!=</span> <span class="re1">$string</span><span class="br0">&#123;</span><span class="re1">$i</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#125;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$string</span> <span class="sy0">.=</span> &nbsp;<span class="re1">$r</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$i</span><span class="sy0">&#8211;;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// return the string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$string</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>User registration will now look a little differently:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="coMULTI">/* Add user to the database */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$username</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$password</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$salt</span> <span class="sy0">=</span> randomString<span class="br0">&#40;</span><span class="nu0">40</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="st0">&#39;root&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pass</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$conn</span> <span class="sy0">=</span> <span class="kw2">new</span> PDO<span class="br0">&#40;</span><span class="st0">&#39;mysql:host=localhost;dbname=test&#39;</span><span class="sy0">,</span> <span class="re1">$user</span><span class="sy0">,</span> <span class="re1">$pass</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="st0">&#39;INSERT INTO users (username, password_hash) VALUES (?, CONCAT(?, sha1(CONCAT(?, ?))))&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$username</span><span class="sy0">,</span> <span class="re1">$salt</span><span class="sy0">,</span> <span class="re1">$salt</span><span class="sy0">,</span> <span class="re1">$password</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<p>And when a user attempts to log in:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="coMULTI">/* Check user credentials */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$username</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;username&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$password</span> <span class="sy0">=</span> <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">&#39;password&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="st0">&#39;root&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pass</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$conn</span> <span class="sy0">=</span> <span class="kw2">new</span> PDO<span class="br0">&#40;</span><span class="st0">&#39;mysql:host=localhost;dbname=test&#39;</span><span class="sy0">,</span> <span class="re1">$user</span><span class="sy0">,</span> <span class="re1">$pass</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="st0">&#39;SELECT * FROM users WHERE username = ?&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$username</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$password_hash</span> <span class="sy0">=</span> <span class="kw3">substr</span><span class="br0">&#40;</span><span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">password_hash</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">40</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="kw3">sha1</span><span class="br0">&#40;</span><span class="kw3">substr</span><span class="br0">&#40;</span><span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">password_hash</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">40</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="re1">$password</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$user</span> <span class="sy0">!=</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$password_hash</span> <span class="sy0">==</span> <span class="re1">$user</span><span class="sy0">-&gt;</span><span class="me1">password_hash</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// user has logged in successfully</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/06/password-hashes-and-salts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to properly use Zend_Paginator</title>
		<link>http://blog.richardknop.com/2009/06/how-to-properly-use-zend_paginator/</link>
		<comments>http://blog.richardknop.com/2009/06/how-to-properly-use-zend_paginator/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 12:36:24 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Pagination]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=272</guid>
		<description><![CDATA[Zend_Paginator is one of the best pagination classes you can find on the Web these days. It is flexible and works with any data collections (not just relational databases). Unfortunately, many people use it incorrectly. The mistake they&#8217;re making is passing a complete dataset to the paginaton class which gets slower and extremely inefficient as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://framework.zend.com/manual/en/zend.paginator.html">Zend_Paginator</a> is one of the best pagination classes you can find on the Web these days. It is flexible and works with any data collections (not just relational databases).</p>
<p>Unfortunately, many people use it incorrectly. The mistake they&#8217;re making is passing a complete dataset to the paginaton class which gets slower and extremely inefficient as the amount of data in the database grows.</p>
<p>The solution is to pass only a select object to the pagination class. I usually write a special method that returns only a select object without fetching any data:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Posts <span class="kw2">extends</span> Zend_Db_Table_Abstract</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; protected <span class="re1">$_name</span> <span class="sy0">=</span> <span class="st0">&#39;posts&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> getSelect<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">select</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$select</span><span class="sy0">-&gt;</span><span class="me1">order</span><span class="br0">&#40;</span><span class="st0">&#39;id DESC&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$select</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>The rest is quite straightforward. In the controller I initialize a Zend_Paginator instance, configure it (I use $_GET['p'] for a current page number) and pass it to the view. Notice the _getTable() method. It saves me lots of time because I don&#8217;t have to include and initialize models manually:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> IndexController <span class="kw2">extends</span> Zend_Controller_Action</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="re1">$_tables</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">private</span> <span class="kw2">function</span> _getTable<span class="br0">&#40;</span><span class="re1">$table</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span>_tables<span class="br0">&#91;</span><span class="re1">$table</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">include</span> APPLICATION_PATH <span class="sy0">.</span> <span class="st0">&#39;/modules/default/models/&#39;</span> <span class="sy0">.</span> <span class="re1">$table</span> <span class="sy0">.</span> <span class="st0">&#39;.php&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span>_tables<span class="br0">&#91;</span><span class="re1">$table</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> <span class="re1">$table</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_tables<span class="br0">&#91;</span><span class="re1">$table</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> indexAction<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$request</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">getRequest</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$posts</span> <span class="sy0">=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span>_getTable<span class="br0">&#40;</span><span class="st0">&#39;Posts&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$paginator</span> <span class="sy0">=</span> Zend_Paginator<span class="sy0">::</span><span class="me2">factory</span><span class="br0">&#40;</span><span class="re1">$posts</span><span class="sy0">-&gt;</span><span class="me1">getSelect</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$paginator</span><span class="sy0">-&gt;</span><span class="me1">setCurrentPageNumber</span><span class="br0">&#40;</span><span class="re1">$request</span><span class="sy0">-&gt;</span><span class="me1">getParam</span><span class="br0">&#40;</span><span class="st0">&#39;p&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$paginator</span><span class="sy0">-&gt;</span><span class="me1">setItemCountPerPage</span><span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">view</span><span class="sy0">-&gt;</span><span class="me1">posts</span> <span class="sy0">=</span> <span class="re1">$paginator</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Then in the view I iterate through the data (in this example scenario blog posts) and print the pagination control:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">count</span><span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">posts</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">posts</span> <span class="kw1">as</span> <span class="re1">$post</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="co1">// display a post content here etc ?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endforeach</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">paginationControl</span><span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">posts</span><span class="sy0">,</span> <span class="st0">&#39;Sliding&#39;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;pagination.phtml&#39;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>I use this pagination template (it&#8217;s very similar to the one in the Zend Framework documentation, I use a more semantic markup though):</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">pageCount</span> <span class="sy0">&gt;</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>ul <span class="kw2">class</span><span class="sy0">=</span><span class="st0">&quot;pagination&quot;</span><span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;!&#8211;</span> Previous page <span class="kw3">link</span> <span class="sy0">&#8211;&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">previous</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>a href<span class="sy0">=</span><span class="st0">&quot;&lt;?php echo $this-&gt;url(array(&#39;module&#39; =&gt; &#39;default&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;controller&#39; =&gt; &#39;index&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;action&#39; =&gt; &#39;index&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;p&#39; =&gt; $this-&gt;previous),</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; null,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true); ?&gt;&quot;</span><span class="sy0">&gt;&lt;</span>img src<span class="sy0">=</span><span class="st0">&quot;/css/previous.png&quot;</span> alt<span class="sy0">=</span><span class="st0">&quot;previous&quot;</span> title<span class="sy0">=</span><span class="st0">&quot;previous&quot;</span> <span class="sy0">/&gt;&lt;/</span>a<span class="sy0">&gt;&lt;/</span>li<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">else</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>img src<span class="sy0">=</span><span class="st0">&quot;/css/previous.png&quot;</span> alt<span class="sy0">=</span><span class="st0">&quot;previous&quot;</span> title<span class="sy0">=</span><span class="st0">&quot;previous&quot;</span> <span class="sy0">/&gt;&lt;/</span>li<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;!&#8211;</span> Numbered page links <span class="sy0">&#8211;&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">pagesInRange</span> <span class="kw1">as</span> <span class="re1">$page</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$page</span> <span class="sy0">!=</span> <span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">current</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>a href<span class="sy0">=</span><span class="st0">&quot;&lt;?php echo $this-&gt;url(array(&#39;module&#39; =&gt; &#39;default&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;controller&#39; =&gt; &#39;index&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;action&#39; =&gt; &#39;index&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;p&#39; =&gt; $page),</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; null,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true); ?&gt;&quot;</span><span class="sy0">&gt;&lt;</span>?php <span class="kw3">echo</span> <span class="re1">$page</span><span class="sy0">;</span> ?<span class="sy0">&gt;&lt;/</span>a<span class="sy0">&gt;&lt;/</span>li<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">else</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>?php <span class="kw3">echo</span> <span class="re1">$page</span><span class="sy0">;</span> <span class="kw2">?&gt;</span> <span class="sy0">&lt;/</span>li<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endforeach</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;!&#8211;</span> <span class="kw3">Next</span> page <span class="kw3">link</span> <span class="sy0">&#8211;&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$this</span><span class="sy0">-&gt;</span><span class="me1">next</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>a href<span class="sy0">=</span><span class="st0">&quot;&lt;?php echo $this-&gt;url(array(&#39;module&#39; =&gt; &#39;default&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;controller&#39; =&gt; &#39;index&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;action&#39; =&gt; &#39;index&#39;,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#39;p&#39; =&gt; $this-&gt;next),</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; null,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true); ?&gt;&quot;</span><span class="sy0">&gt;&lt;</span>img src<span class="sy0">=</span><span class="st0">&quot;/css/next.png&quot;</span> alt<span class="sy0">=</span><span class="st0">&quot;next&quot;</span> title<span class="sy0">=</span><span class="st0">&quot;next&quot;</span> <span class="sy0">/&gt;&lt;/</span>a<span class="sy0">&gt;&lt;/</span>li<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">else</span><span class="sy0">:</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>img src<span class="sy0">=</span><span class="st0">&quot;/css/next.png&quot;</span> alt<span class="sy0">=</span><span class="st0">&quot;next&quot;</span> title<span class="sy0">=</span><span class="st0">&quot;next&quot;</span> <span class="sy0">/&gt;&lt;/</span>li<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">&lt;/</span>ul<span class="sy0">&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>I often have more than one pagination template so I usually create a <em>path/to/a/module/views/scripts/pagination</em> directory where I keep them.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/06/how-to-properly-use-zend_paginator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nested set model</title>
		<link>http://blog.richardknop.com/2009/05/nested-set-model/</link>
		<comments>http://blog.richardknop.com/2009/05/nested-set-model/#comments</comments>
		<pubDate>Fri, 22 May 2009 16:07:20 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Nested set model]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=161</guid>
		<description><![CDATA[In the previous post I explained the adjacency list model and how to implement it in PHP. There is an alternative &#8211; the nested set model (also called modified preorder tree traversal). It is more complicated than the adjacency model but there is a reason why it might be better in certain situations: unlimited hierarchy [...]]]></description>
			<content:encoded><![CDATA[<p>In the previous post I explained the <a href="http://blog.richardknop.com/2009/05/adjacency-list-model/">adjacency list model</a> and how to implement it in PHP. There is an alternative &#8211; the nested set model (also called modified preorder tree traversal). It is more complicated than the adjacency model but there is a reason why it might be better in certain situations:</p>
<ul>
<li>unlimited hierarchy levels</li>
</ul>
<p>On the other hand, there are reasons why I wouldn&#8217;t recommend using it unless you have to:</p>
<ul>
<li>very complicated hierarchy modifications compared to the adjacency model  (you often have to update almost the whole table)</li>
<li>a small mistake in PHP code for modifying the hierarchy can break up the whole table (you must test your application carefully before deploying it to the production environment)</li>
</ul>
<p>Look at the picture to get a better idea about what the nested set model looks like:</p>
<p><img class="alignnone size-full wp-image-175" title="Nested set model" src="http://blog.richardknop.com/wp-content/uploads/2009/05/nested-set-model.gif" alt="Nested set model" width="593" height="313" /></p>
<p>Pay special attention to the red numbers &#8211; based on these numbers you can calculate the position of an item in the hierarchy. The schema (&#8216;lft&#8217; and &#8216;rgt&#8217; are used because &#8216;left&#8217; and &#8216;right&#8217; are MySQL reserved words):</p>
<pre>CREATE TABLE categories (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;</pre>
<p>Let’s populate the table with some content we can work with:</p>
<pre>INSERT INTO categories (id, name, lft, rgt) VALUES
(NULL, 'Relational databases', 1, 12),
(NULL, 'SQLite', 2, 3),
(NULL, 'MySQL', 4, 9),
(NULL, 'PDO', 5, 6),
(NULL, 'Transactions', 7, 8),
(NULL, 'PostgreSQL', 10, 11);</pre>
<p>The query to select the full tree is simple:</p>
<pre>SELECT * FROM categories ORDER BY lft</pre>
<h2>PHP implementation</h2>
<p>Displaying the tree in an unordered XHTML list is not the hardest part. There are two important formulas:</p>
<pre>rgt &lt; last rgt =&gt; increment the hierarchy level (move one level down)
lft - last lft &gt; 2 =&gt; decrement the hierarchy level (move one level up)</pre>
<p>Therefor you can create the unordered list by keeping a track of left and right values:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="st0">&#39;root&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pass</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$conn</span> <span class="sy0">=</span> <span class="kw2">new</span> PDO<span class="br0">&#40;</span><span class="st0">&#39;mysql:host=localhost;dbname=test&#39;</span><span class="sy0">,</span> <span class="re1">$user</span><span class="sy0">,</span> <span class="re1">$pass</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$sql</span> <span class="sy0">=</span><span class="st0">&#39;SELECT * FROM categories ORDER BY lft&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">query</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$categories</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$left</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$right</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$level</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">while</span> <span class="br0">&#40;</span><span class="re1">$row</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">empty</span><span class="br0">&#40;</span><span class="re1">$right</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$lastRight</span> <span class="sy0">=</span> <span class="kw3">end</span><span class="br0">&#40;</span><span class="re1">$right</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$lastRight</span> <span class="sy0">&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$level</span> <span class="sy0">=</span> <span class="re1">$level</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">empty</span><span class="br0">&#40;</span><span class="re1">$left</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$lastLeft</span> <span class="sy0">=</span> <span class="kw3">end</span><span class="br0">&#40;</span><span class="re1">$left</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lft</span> <span class="sy0">-</span> <span class="re1">$lastLeft</span> <span class="sy0">&gt;</span> <span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$level</span> <span class="sy0">=</span> <span class="re1">$level</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;id&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">id</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;name&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#39;level&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$level</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$left</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lft</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$right</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#39;&lt;ul&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$count</span> <span class="sy0">=</span> <span class="kw3">count</span><span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$count</span> <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;li&gt;&#39;</span><span class="sy0">,</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;name&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="st0">&#39;&lt;/li&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;li&gt;&#39;</span><span class="sy0">,</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;name&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$count</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;ul&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;/li&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span> <span class="sy0">&lt;</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="kw3">str_repeat</span><span class="br0">&#40;</span><span class="st0">&#39;&lt;/ul&gt;&lt;/li&gt;&#39;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span> <span class="sy0">-</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;li&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="kw3">str_repeat</span><span class="br0">&#40;</span><span class="st0">&#39;&lt;/ul&gt;&lt;/li&gt;&#39;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">,</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$i</span><span class="sy0">++;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#39;&lt;/ul&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<h2>Modifying the hierarchy</h2>
<p>This is where it gets interesting. Modifying the hierarchy created by the nested set model or in other words adding, updating or removing branches (nodes) from the tree while keeping the hierarchy integrity.</p>
<h3>Adding nodes</h3>
<p>There are two ways how to add a new node &#8211; from the left and from the right. Both have very similar implementation (I will show you just the latter). Before I show you how to do it here is another important formula:</p>
<pre>(rgt - lft - 1) / 2 = number of children nodes</pre>
<p>In theory, what you need to do is add a new node and update all nodes to the right (those that have higher &#8216;rgt&#8217; value). First, here is the algorithm in the pseudo language:</p>
<pre>get a parent node

for all nodes
    if rgt &gt;= parent-&gt;rgt
        rgt = rgt + 2
        if lft &lt;&gt; 1 and lft &gt; parent-&gt;lft
            lft = lft + 2
        endif
    endif
endfor

add a new node:
    lft = parent-&gt;lft + number of children nodes * 2 + 1
    rgt = lft + 1</pre>
<p>Here is a function:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> addNodeFromRight<span class="br0">&#40;</span><span class="re1">$conn</span><span class="sy0">,</span> <span class="re1">$parentId</span><span class="sy0">,</span> <span class="re1">$name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; try <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>PDO<span class="sy0">::</span><span class="me2">ATTR_ERRMODE</span><span class="sy0">,</span> PDO<span class="sy0">::</span><span class="me2">ERRMODE_EXCEPTION</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">beginTransaction</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;SELECT * FROM categories WHERE id = ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$parentId</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$parent</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;UPDATE categories SET rgt = rgt + 2 WHERE rgt &gt;= ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$parent</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;UPDATE categories SET lft = lft + 2 WHERE rgt &gt;= ? AND lft &lt;&gt; 1 AND lft &gt; ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$parent</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="sy0">,</span> <span class="re1">$parent</span><span class="sy0">-&gt;</span><span class="me1">lft</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;INSERT INTO categories (name, lft, rgt) VALUES (?, ?, ?)&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$numberOfChildren</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="re1">$parent</span><span class="sy0">-&gt;</span><span class="me1">rgt</span> <span class="sy0">-</span> <span class="re1">$parent</span><span class="sy0">-&gt;</span><span class="me1">lft</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu0">2</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$lft</span> <span class="sy0">=</span> <span class="re1">$parent</span><span class="sy0">-&gt;</span><span class="me1">lft</span> <span class="sy0">+</span> <span class="re1">$numberOfChildren</span> <span class="sy0">*</span> <span class="nu0">2</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$rgt</span> <span class="sy0">=</span> <span class="re1">$lft</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$name</span><span class="sy0">,</span> <span class="re1">$lft</span><span class="sy0">,</span> <span class="re1">$rgt</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>PDOException <span class="re1">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">rollback</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="re1">$e</span><span class="sy0">-&gt;</span><span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h3>Removing nodes</h3>
<p>Very similar to adding nodes but you must also take special care of children branches in case you want to remove a parent node. In the pseudo language:</p>
<pre>get a node

if node-&gt;lft &lt;&gt; 1

    delete the node

    for all nodes
        if rgt &gt; node-&gt;rgt
            rgt = rgt - 2
        endif
        if rgt &gt; node-&gt;rgt and lft &lt;&gt; 1 and lft &gt; node-&gt;lft
            lft = lft - 2
        endif
        if rgt &lt; node-&gt;rgt and lft &gt; node-&gt;lft
            lft = lft - 1
            rgt = rgt - 1
        endif
    endfor

endif</pre>
<p>And here&#8217;s how it could look in PHP:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> removeNode<span class="br0">&#40;</span><span class="re1">$conn</span><span class="sy0">,</span> <span class="re1">$id</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; try <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>PDO<span class="sy0">::</span><span class="me2">ATTR_ERRMODE</span><span class="sy0">,</span> PDO<span class="sy0">::</span><span class="me2">ERRMODE_EXCEPTION</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">beginTransaction</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;SELECT * FROM categories WHERE id = ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$id</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$node</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$node</span><span class="sy0">-&gt;</span><span class="me1">lft</span> <span class="sy0">&lt;&gt;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;DELETE FROM categories WHERE id = ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$id</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;UPDATE categories SET rgt = rgt &#8211; 2 WHERE rgt &gt; ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$node</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;UPDATE categories SET lft = lft &#8211; 2 WHERE rgt &gt; ? AND lft &lt;&gt; 1 AND lft &gt; ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$node</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="sy0">,</span> <span class="re1">$node</span><span class="sy0">-&gt;</span><span class="me1">lft</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$sql</span> <span class="sy0">=</span> <span class="st0">&#39;UPDATE categories SET lft = lft &#8211; 1, rgt = rgt &#8211; 1 WHERE rgt &lt; ? AND lft &gt; ?&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">prepare</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="re1">$node</span><span class="sy0">-&gt;</span><span class="me1">rgt</span><span class="sy0">,</span> <span class="re1">$node</span><span class="sy0">-&gt;</span><span class="me1">lft</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>PDOException <span class="re1">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">rollback</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="re1">$e</span><span class="sy0">-&gt;</span><span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Note that I made sure that lft is not equal to 1 before removing the node. You cannot remove the top node or else the whole tree hierarchy will break up.</p>
<h3>Updating nodes</h3>
<p>You might have already guessed it &#8211; to update a node you can combine addNodeFromRight() and removeNode() functions.</p>
<p>That&#8217;s not the most efficient way to do it though. I&#8217;m too tired to think about the algorithm now but I&#8217;m sure you can figure it out after reading this post.</p>
<h2>A small trick</h2>
<p>Most of the time you will need a hierarchy with more separate trees (or subhierarchies) which would be much more complicated to achieve. There&#8217;s a small trick you can use though. Just don&#8217;t display the top node (it could be named &#8216;Categories&#8217; in this case) and decrease the hierarchy level in the script by 1.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/05/nested-set-model/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adjacency list model</title>
		<link>http://blog.richardknop.com/2009/05/adjacency-list-model/</link>
		<comments>http://blog.richardknop.com/2009/05/adjacency-list-model/#comments</comments>
		<pubDate>Tue, 19 May 2009 15:26:46 +0000</pubDate>
		<dc:creator>Richard Knop</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Adjacency list model]]></category>

		<guid isPermaLink="false">http://blog.richardknop.com/?p=121</guid>
		<description><![CDATA[Managing hierarchical data in relational databases (such as MySQL) is a troublesome task because relational databases were not designed to store hierarchical data. MySQL tables are just flat files with no representation of a parent-child relationship. There are two methods that are usually used to store hierarchical data in MySQL: adjacency list model modified tree [...]]]></description>
			<content:encoded><![CDATA[<p>Managing hierarchical data in relational databases (such as MySQL) is a troublesome task because relational databases were not designed to store hierarchical data. MySQL tables are just flat files with no representation of a parent-child relationship. There are two methods that are usually used to store hierarchical data in MySQL:</p>
<ul>
<li>adjacency list model</li>
<li><a href="http://blog.richardknop.com/2009/05/nested-set-model/">modified tree preorder traversal (also called nested set model)</a></li>
</ul>
<p>In this post I will show you how to use the adjacency list model and how to implement it in PHP. Look at the picture to get a better idea about what the adjacency model looks like:</p>
<p><img class="alignnone size-full wp-image-174" title="Adjacency list model" src="http://blog.richardknop.com/wp-content/uploads/2009/05/adjacency-list-model.gif" alt="Adjacency list model" width="593" height="313" /></p>
<p>As you can see the hierarchy is created by parent-child relationships. A typical example would be categories in WordPress where every category can have zero or one parent.</p>
<p>How is this achieved in the database? The table just need to have an additional column with the id of the parent. In addition, this column should allow NULL values. For instance:</p>
<pre>CREATE TABLE categories (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
parent_id INT NULL DEFAULT NULL,
FOREIGN KEY (parent_id) REFERENCES categories(id) ON UPDATE CASCADE,
INDEX (parent_id),
PRIMARY KEY (id)
) ENGINE = INNODB;</pre>
<p>Let&#8217;s populate the table with some content we can work with:</p>
<pre>INSERT INTO categories (id, name, parent_id) VALUES
(NULL, 'Relational databases', NULL),
(NULL, 'SQLite', 1),
(NULL, 'MySQL', 1),
(NULL, 'PostgreSQL', 1),
(NULL, 'PDO', 3),
(NULL, 'Transactions', 3);</pre>
<p>Adding, editing or removing categories from this table is easy. The query to select the full tree is more complex though:</p>
<pre>SELECT t0.id AS lvl0_id, t0.name AS lvl0_name,
t1.id AS lvl1_id, t1.name as lvl1_name,
t2.id AS lvl2_id, t2.name as lvl2_name,
t3.id AS lvl3_id, t3.name as lvl3_name,
t4.id AS lvl4_id, t4.name as lvl4_name
FROM categories AS t0
LEFT JOIN categories AS t1 ON t1.parent_id = t0.id
LEFT JOIN categories AS t2 ON t2.parent_id = t1.id
LEFT JOIN categories AS t3 ON t3.parent_id = t2.id
LEFT JOIN categories AS t4 ON t4.parent_id = t3.id
ORDER BY t0.id, t1.id, t2.id, t3.id, t4.id;</pre>
<h2>PHP implementation</h2>
<p>Now the intriguing part. You will usually want to display the tree in a nested unordered XHTML list. There are many ways to do it, here is my approach:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="re1">$user</span> <span class="sy0">=</span> <span class="st0">&#39;root&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pass</span> <span class="sy0">=</span> <span class="st0">&#39;&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$conn</span> <span class="sy0">=</span> <span class="kw2">new</span> PDO<span class="br0">&#40;</span><span class="st0">&#39;mysql:host=localhost;dbname=test&#39;</span><span class="sy0">,</span> <span class="re1">$user</span><span class="sy0">,</span> <span class="re1">$pass</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$sql</span> <span class="sy0">=</span><span class="st0">&#39;SELECT t0.id AS lvl0_id, t0.name AS lvl0_name,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">t1.id AS lvl1_id, t1.name as lvl1_name,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">t2.id AS lvl2_id, t2.name as lvl2_name,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">t3.id AS lvl3_id, t3.name as lvl3_name,</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">t4.id AS lvl4_id, t4.name as lvl4_name</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">FROM categories AS t0</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">LEFT JOIN categories AS t1 ON t1.parent_id = t0.id</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">LEFT JOIN categories AS t2 ON t2.parent_id = t1.id</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">LEFT JOIN categories AS t3 ON t3.parent_id = t2.id</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">LEFT JOIN categories AS t4 ON t4.parent_id = t3.id</span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0">ORDER BY t0.id, t1.id, t2.id, t3.id, t4.id&#39;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$conn</span><span class="sy0">-&gt;</span><span class="me1">query</span><span class="br0">&#40;</span><span class="re1">$sql</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$categories</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$pool</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">while</span> <span class="br0">&#40;</span><span class="re1">$row</span> <span class="sy0">=</span> <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetchObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl0_id</span><span class="sy0">,</span> <span class="re1">$pool</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl0_name</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$c</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;id&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl0_id</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;name&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl0_name</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;level&#39;</span> <span class="sy0">=&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$c</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl1_id</span><span class="sy0">,</span> <span class="re1">$pool</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl1_name</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$c</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;id&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl1_id</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;name&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl1_name</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;level&#39;</span> <span class="sy0">=&gt;</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$c</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl2_id</span><span class="sy0">,</span> <span class="re1">$pool</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl2_name</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$c</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;id&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl2_id</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;name&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl2_name</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;level&#39;</span> <span class="sy0">=&gt;</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$c</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl3_id</span><span class="sy0">,</span> <span class="re1">$pool</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl3_name</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$c</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;id&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl3_id</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;name&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl3_name</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;level&#39;</span> <span class="sy0">=&gt;</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$c</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl4_id</span><span class="sy0">,</span> <span class="re1">$pool</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="kw2">false</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl4_name</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$c</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st0">&#39;id&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl4_id</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;name&#39;</span> <span class="sy0">=&gt;</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl4_name</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#39;level&#39;</span> <span class="sy0">=&gt;</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$c</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$pool</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl0_id</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$pool</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl1_id</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$pool</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl2_id</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$pool</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl3_id</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$pool</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re1">$row</span><span class="sy0">-&gt;</span><span class="me1">lvl4_id</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#39;&lt;ul&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re1">$count</span> <span class="sy0">=</span> <span class="kw3">count</span><span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$count</span> <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;li&gt;&#39;</span><span class="sy0">,</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;name&#39;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="st0">&#39;&lt;/li&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;li&gt;&#39;</span><span class="sy0">,</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;name&#39;</span><span class="br0">&#93;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$i</span> <span class="sy0">&lt;</span> <span class="re1">$count</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;ul&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;/li&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span> <span class="sy0">&lt;</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="kw3">str_repeat</span><span class="br0">&#40;</span><span class="st0">&#39;&lt;/ul&gt;&lt;/li&gt;&#39;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">,</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span> <span class="sy0">-</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&#39;&lt;li&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="kw3">str_repeat</span><span class="br0">&#40;</span><span class="st0">&#39;&lt;/ul&gt;&lt;/li&gt;&#39;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">,</span> <span class="re1">$categories</span><span class="br0">&#91;</span><span class="re1">$i</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#39;level&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re1">$i</span><span class="sy0">++;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> <span class="st0">&#39;&lt;/ul&gt;&#39;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="sy0">;</span></div>
</li>
</ol>
</div>
<h2>Disadvantages</h2>
<ul>
<li>limited hierarchy levels (not a big problem as you can easily modify the SQL query for any amount of levels)</li>
<li>complex and long-winded PHP implementation</li>
</ul>
<h2>Advantages</h2>
<ul>
<li>fast (you need only a single SQL query &#8211; much much faster than the usual recursion method)</li>
<li>very simple hierarchy modifications (you need to update only a single table row each time &#8211; not the whole table as in the nested set model)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.richardknop.com/2009/05/adjacency-list-model/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
