<?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>Jamie Nay &#187; Zend Framework</title>
	<atom:link href="http://jamienay.com/category/php-code/zend-framework-php-code-2/feed/" rel="self" type="application/rss+xml" />
	<link>http://jamienay.com</link>
	<description>A PHP web developer writing about the web.</description>
	<lastBuildDate>Wed, 02 Jun 2010 17:09:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Cipher Behavior with Zend_Filter for CakePHP 1.3 &#8211; Easy Two-Way Encryption</title>
		<link>http://jamienay.com/2010/02/cipher-behavior-with-zend_filter-for-cakephp-1-3-easy-two-way-encryption/</link>
		<comments>http://jamienay.com/2010/02/cipher-behavior-with-zend_filter-for-cakephp-1-3-easy-two-way-encryption/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 04:29:00 +0000</pubDate>
		<dc:creator>Jamie</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[data retrieval]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://jamienay.com/?p=547</guid>
		<description><![CDATA[Here&#8217;s a quickie &#8211; a Cipher behavior for CakePHP to handle two-way encryption of sensitive data. If you want to store, say, credit card information, you&#8217;ll need a way to retrieve it later; Cake&#8217;s built-in security hashing is one-way, meaning that once it&#8217;s encrypted it ain&#8217;t comin&#8217; back. So, I turned to the Zend Framework [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quickie &#8211; a Cipher behavior for CakePHP to handle two-way encryption of sensitive data. If you want to store, say, credit card information, you&#8217;ll need a way to retrieve it later; Cake&#8217;s built-in security hashing is one-way, meaning that once it&#8217;s encrypted it ain&#8217;t comin&#8217; back. So, I turned to the Zend Framework and brought in Zend_Filter_Encrypt and Zend_Filter_Decrypt to handle the heavy lifting. This behavior uses <strong>mcrypt</strong>, so you need to have that PHP extension installed, which (as far as I can tell) is fairly standard.</p>
<p><strong><a href="http://github.com/jamienay/cipher_behavior">Download the Cipher Behavior Source on Github</a></strong></p>
<p>First things first &#8211; you need to throw a couple of libraries from the Zend Framework into your vendors folder. Yup, I love my Zend! CakePHP teams up very well with ZF.</p>
<p>You&#8217;ll need the following Zend Framework libraries (<a href="http://framework.zend.com/download/latest" target="_blank">download the framework</a>):</p>
<ul>
<li> Zend_Filter (Zend/Filter.php and Zend/Filter)</li>
<li>Zend_Loader (Zend/Loader.php and Zend/Loader)</li>
</ul>
<p>Put those files in your vendors folder. You&#8217;ll also need to update your include_path somewhere (say, app/bootstrap.php) with the following:</p>
<pre>
ini_set('include_path', ini_get('include_path') . ':' . APP . '/vendors');
</pre>
<p>I also recommend defining an autoload function somewhere for Zend classes (again, bootstrap.php is a good choice). A simple, Zend-only autoloader might look like this:</p>
<pre class="brush: php">
function __autoload($path) {
	if (substr($path, 0, 5) == &#039;Zend_&#039;) {
		include str_replace(&#039;_&#039;, &#039;/&#039;, $path) . &#039;.php&#039;;
	}
	return $path;
}
</pre>
<p>The behavior has three config options:</p>
<ul>
<li><strong>key</strong>: the encryption key to use. If null (default), then it&#8217;ll use the value of Configure::read(&#8216;Security.salt&#8217;).</li>
<li><strong>automatic</strong>: whether to automatically encrypt and decrypt data as it&#8217;s saved/retrieved. Defaults to true.</li>
<li><strong>fields</strong>: an array of fields belong to the model that should be encrypted</li>
</ul>
<p>Usage of the behavior itself is straightforward: just add Cipher to the $actsAs array of any model you&#8217;d like:</p>
<pre class="brush: php">
Class User extends AppModel {
    var $actsAs = array(&#039;Cipher&#039;);
}

Class Order extends AppModel {
    var $actsAs = array(&#039;Cipher&#039; =&gt; array(&#039;fields&#039; =&gt; array(&#039;credit_card&#039;, &#039;expiry&#039;)));
}
</pre>
<p>You can also manually decrypt and encrypt data, either by passing an array of find results (in which case the fields specified in &#8216;fields&#8217; will be encrypted/decrypted), or by passing a string:</p>
<pre class="brush: php">
// Manually encrypt/decrypt the results of Model::find()
$encrypted = $this-&gt;encrypt($findResults);
$decrypted = $this-&gt;decrypt($encrypted );

// Manually encrypt/decrypt a string
$encryptedSecretString= $this-&gt;encrypt(&#039;my secret string&#039;);
$decryptedString = $this-&gt;decrypt($encryptedSecretString);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jamienay.com/2010/02/cipher-behavior-with-zend_filter-for-cakephp-1-3-easy-two-way-encryption/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Zend_Search_Lucene Datasource for CakePHP</title>
		<link>http://jamienay.com/2010/01/zend_search_lucene-datasource-for-cakephp/</link>
		<comments>http://jamienay.com/2010/01/zend_search_lucene-datasource-for-cakephp/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 21:53:33 +0000</pubDate>
		<dc:creator>Jamie</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[data retrieval]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://jamienay.com/?p=512</guid>
		<description><![CDATA[Major update January 22/10: much of the content of this article has been updated to reflect the changes to the datasource, the latest version of which you can download on Github. Just out of the oven &#8211; a Zend_Search_Lucene datasource for CakePHP (built with 1.2 but probably works just fine in 1.3) that I originally [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Major update January 22/10:</strong> much of the content of this article has been updated to reflect the changes to the datasource, the latest version of which you can <a href="http://github.com/jamienay/zend_search_lucene_source">download on Github</a>.</p>
<p>Just out of the oven &#8211; a Zend_Search_Lucene datasource for CakePHP (built with 1.2 but probably works just fine in 1.3) that I originally wrote for an in-house CMS site search plugin. I can&#8217;t release the plugin itself (and there&#8217;s so much CMS-specific code that it would need a lot of work to make it generic anyway), but I thought that someone might find the datasource itself useful. It&#8217;s pretty basic at this point and doesn&#8217;t implement some of the fancier Zend_Search_Lucene features such as sorting (it just returns sorted in score order, which is probably what you want anyway).</p>
<p>Zend_Search_Lucene is a text-based search index system for developers who don&#8217;t want to (or can&#8217;t) use a database for search indexing.</p>
<p><a href="http://github.com/jamienay/zend_search_lucene_source">Download the current version of the ZendSearchLuceneDatsource from my Github repository</a>.</p>
<p>I won&#8217;t go into detail about how to add data into the Lucene database since the <a href="http://framework.zend.com/manual/en/zend.search.lucene.html">Zend Framework documention</a> is so good (CakePHP should be jealous!). You&#8217;ll find all the info you need there. There are also a couple of older articles out there that show how you can integrate Zend_Search_Lucene into CakePHP:</p>
<ul>
<li><a href="http://cakephptips.blogspot.com/2008/04/build-your-own-search-engine-in-php_5060.html">Build your own search engine in PHP</a></li>
<li><a href="http://bakery.cakephp.org/articles/view/integrating-zend-framework-lucene-with-your-cake-application">Integrating Zend Framework Lucene with your Cake Application</a></li>
</ul>
<p><strong>Setup</strong></p>
<p><strong>First</strong>, copy zend_search_lucene.php to models/datasources.</p>
<p>Then, you&#8217;ll need to download the Zend_Search_Lucene library from the Zend Framework website and put some files into your /vendors directory:</p>
<ul>
<li>Zend/Search (the directory and all of its contents)</li>
<li>Zend/Exception.php</li>
</ul>
<p>You&#8217;ll also need to update your include path to include app/vendors, since the Zend Framework loads a lot of classes on its own. I also made a little autoload function to make the loading of Zend Framework classes easier. Put the following code somewhere common, such as app/bootstrap.php:</p>
<pre class="brush: php">
ini_set(&#039;include_path&#039;, ini_get(&#039;include_path&#039;) . &#039;:&#039; . CAKE_CORE_INCLUDE_PATH . DS . &#039;/vendors&#039;);
function __autoload($path) {
if (substr($path, 0, 5) == &#039;Zend_&#039;) {
include str_replace(&#039;_&#039;, &#039;/&#039;, $path) . &#039;.php&#039;;
}
return $path;
}
</pre>
<p>You also need to put the DB config for the datasource in config/database.php (<strong>updated Jan 20/2010 for better DebugKit compatibility</strong>):</p>
<pre class="brush: php">
var $zendSearchLucene = array(
	&#039;datasource&#039; =&gt; &#039;ZendSearchLucene&#039;,
	&#039;indexFile&#039; =&gt; &#039;lucene&#039;, // stored in the cache dir.
	&#039;driver&#039; =&gt; &#039;&#039;,
	&#039;source&#039; =&gt; &#039;search_indices&#039;
);
</pre>
<p>Then, in the model that&#8217;ll act as your search index (say, for example, SearchIndex), specify the DB config:</p>
<pre class="brush: php">
&lt;?php class SearchIndex extends AppModel {
var $useDbConfig = &#039;zendSearchLucene&#039;;
}
?&gt;
</pre>
<p><strong>Saving/Indexing</strong></p>
<p>I&#8217;ve tried to keep the datasource functions as simple and familiar as possible. When saving an item to the index, the datasource expects a multidimensional array for each item. For compatibility with CakePHP&#8217;s datasource code, the &#8216;meat&#8217; of the data is nested in the third level of the array. Each sub-array contains information about a field to be stored. For example:</p>
<pre class="brush: php">
$saveData = array(&#039;SearchIndex&#039; =&gt; array(
  	&#039;document&#039; =&gt; array(
		array(
			&#039;key&#039; =&gt; &#039;name&#039;,
			&#039;value&#039; =&gt; $record[$Model-&gt;alias][$this-&gt;settings[$Model-&gt;alias][&#039;name&#039;]],
			&#039;type&#039; =&gt; &#039;Text&#039;
		),
		array(
			&#039;key&#039; =&gt; &#039;description&#039;,
			&#039;value&#039; =&gt; $record[$Model-&gt;alias][$this-&gt;settings[$Model-&gt;alias][&#039;description&#039;]],
			&#039;type&#039; =&gt; &#039;Text&#039;
		),
		array(
			&#039;key&#039; =&gt; &#039;url&#039;,
			&#039;value&#039; =&gt; $this-&gt;__constructUrl($Model, $record),
			&#039;type&#039; =&gt; &#039;Text&#039;
		)
	)
 ));
</pre>
<p>Passing that data in a Model::save() call will in turn execute the following Zend code (more or less &#8211; this is a very simplified version of the actual ZendSearchLuceneSource saving code):</p>
<pre class="brush: php">
$index = Zend_Search_Lucene::open(&#039;/path/to/the/index/set/in/dbConfig&#039;);
$doc = new Zend_Search_Lucene_Document();
foreach ($data as $field) {
$doc-&gt;addField(Zend_Search_Lucene_Field::$field[&#039;type&#039;]($field[&#039;key&#039;], $field[&#039;value&#039;]));
}
$index-&gt;addDocument($doc);
</pre>
<p>Obviously that&#8217;s a basic example; you&#8217;ll probably send a whole bunch of dynamic info to the indexer. But that&#8217;s the gist of it anyway.</p>
<p><strong>Querying</strong></p>
<p>You can search for records just like you would a regular datasource. Pass the search terms as a &#8220;query&#8221; condition. If you want the search terms to be highlighted in the returned results, pass <strong>&#8216;highlight&#8217; =&gt; true</strong> in the array of options. Note that only indexed fields will be highlighted.</p>
<p>You can find all results:</p>
<pre class="brush: php">
function search($term) {
$results = $this-&gt;SearchIndex-&gt;find(&#039;all&#039;, array(&#039;highlight&#039; =&gt; true, &#039;conditions&#039; =&gt; array(&#039;query&#039; =&gt; &#039;best cakephp tutorials&#039;)));
}
</pre>
<p>You can mimic Google&#8217;s I&#8217;m Feeling Lucky with find(&#8216;first&#8217;):</p>
<pre class="brush: php">
function search($term) {
$topResult = $this-&gt;SearchIndex-&gt;find(&#039;first&#039;, array(&#039;conditions&#039; =&gt; array(&#039;query&#039; =&gt; &#039;best cakephp tutorials&#039;)));
}
</pre>
<p>You can even paginate:</p>
<pre class="brush: php">
function search($term) {
$this-&gt;paginate = array(
&#039;limit&#039; =&gt; 10,
&#039;conditions&#039; =&gt; array(&#039;query&#039; =&gt; &#039;best CakePHP tutorials&#039;),
&#039;highlight&#039; =&gt; true
);

$results = $this-&gt;paginate();
}
</pre>
<p>Results are returned in the expected CakePHP way, as a multidimensional array &#8211; <strong>$results[0]['MyModelAlias']</strong> for multiple records, <strong>$results['MyModelAlias']</strong> for one (i.e. with find(&#8216;first&#8217;)).</p>
<p>There you go &#8211; enjoy! As always, comments and suggestions are welcomed.</p>
<p>I used the <a href="http://blog.loadsys.com/2009/06/19/cakephp-rss-feed-datasource/">RSS Feed datasource</a> by Loadsys as a guide to good datasource design. I may have borrowed a function or two. <img src='http://jamienay.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><a href="http://www.neilcrookes.com/2009/11/21/cakephp-searchable-plugin">Neil Crookes&#8217; Searchable plugin</a> also helped.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamienay.com/2010/01/zend_search_lucene-datasource-for-cakephp/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Coming soon &#8211; CakePHP and the Zend Framework: together at last!</title>
		<link>http://jamienay.com/2010/01/coming-soon-cakephp-and-the-zend-framework-together-at-last/</link>
		<comments>http://jamienay.com/2010/01/coming-soon-cakephp-and-the-zend-framework-together-at-last/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 19:59:14 +0000</pubDate>
		<dc:creator>Jamie</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[data validation]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://jamienay.com/?p=503</guid>
		<description><![CDATA[Just a quick update &#8211; I&#8217;m currently working on integrating some libraries from the Zend Framework into CakePHP. The first one I&#8217;m doing is Zend_Validate, which is a heavy, robust alternative to CakePHP&#8217;s own Validation class. I&#8217;ll be sharing my results as a plugin when I&#8217;m done. Stay tuned.]]></description>
			<content:encoded><![CDATA[<p>Just a quick update &#8211; I&#8217;m currently working on integrating some libraries from the Zend Framework into CakePHP. The first one I&#8217;m doing is Zend_Validate, which is a heavy, robust alternative to CakePHP&#8217;s own Validation class. I&#8217;ll be sharing my results as a plugin when I&#8217;m done. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamienay.com/2010/01/coming-soon-cakephp-and-the-zend-framework-together-at-last/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Lightweight Autoloading in the Zend Framework</title>
		<link>http://jamienay.com/2009/03/lightweight-autoloading-in-the-zend-framework/</link>
		<comments>http://jamienay.com/2009/03/lightweight-autoloading-in-the-zend-framework/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 01:00:56 +0000</pubDate>
		<dc:creator>Jamie</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.jamienay.com/?p=46</guid>
		<description><![CDATA[The Zend Framework is one of the best things to happen to PHP since the introduction of objects. But one area that&#8217;s always bugged me has been Zend_Loader, specifically its autoloader. For a framework with an extremely rigid class naming structure, you&#8217;d think the autoloader would be light and intuitive. Yet it&#8217;s a lot more [...]]]></description>
			<content:encoded><![CDATA[<p>The Zend Framework is one of the best things to happen to PHP since the introduction of objects. But one area that&#8217;s always bugged me has been Zend_Loader, specifically its autoloader. For a framework with an extremely rigid class naming structure, you&#8217;d think the autoloader would be light and intuitive. Yet it&#8217;s a lot more complex than it needs to be for most developers, leading to some inefficient code and a lot of &#8216;require_once&#8217; statements everywhere, most of which, if we play our cards right, can be deleted. So, here&#8217;s a little autoloader that I wrote for a current project that does the job in nearly every case. Assuming you&#8217;re going to make a method of your Bootstrap class, it&#8217;ll look something like:</p>
<pre class="brush: php">
public static function autoload($path)
{
    include str_replace(&#039;_&#039;, &#039;/&#039;, $path) . &#039;.php&#039;;
    return $path;
}
</pre>
<p>Then when you&#8217;re running the bootstrap, change your default registerAutoload() call to:</p>
<pre class="brush: php">
require_once &#039;Zend/Loader.php&#039;;
Zend_Loader::registerAutoload(&#039;Bootstrap&#039;);
</pre>
<p>And that&#8217;s it! Erase or comment out those annoying and inefficient require_once statementse. I know, slightly ironic that we need a require_once since the goal is to get rid of them. I never said it was perfect &#8211; almost. <img src='http://jamienay.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://jamienay.com/2009/03/lightweight-autoloading-in-the-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
