<?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>Derivante</title>
	<atom:link href="http://www.derivante.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.derivante.com</link>
	<description>to obtain or receive from a source</description>
	<lastBuildDate>Mon, 26 Apr 2010 18:44:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Extensible PHP Caching Library</title>
		<link>http://www.derivante.com/2010/04/23/extensible-php-caching-library/</link>
		<comments>http://www.derivante.com/2010/04/23/extensible-php-caching-library/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 17:31:43 +0000</pubDate>
		<dc:creator>Justin Leider</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Class]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Flexibility]]></category>
		<category><![CDATA[Library]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=765</guid>
		<description><![CDATA[Everyone has probably already seen every caching class there ever was and ever will be. However, when I was searching for a class that could easily be switched from one data store to the next I couldn't find a thing. (&#8230;)</p><p><a href="http://www.derivante.com/2010/04/23/extensible-php-caching-library/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Everyone has probably already seen every caching class there ever was and ever will be. However, when I was searching for a class that could easily be switched from one data store to the next I couldn't find a thing. Every caching class I seemed to come by was written specifically for a single back end and with their predefined static keys/column names. Well, those silly restrictions have come to an end!</p>
<p>I present to you the <a title="PHP Caching Library" href="http://github.com/jleider/extensible-php-caching-library" target="_blank">Extensible PHP Caching Library</a> (Hosted at GitHub) - This collection of classes makes it easy to customize key or column names to your needs as well as switch from one data store to another. This extensibility is baked into the core of the library via an abstract class. This abstract Cache class takes an associative array of keys/columns and determines how to use those keys based on the type of cache back end you are using. For example: Suppose you are using a RDBMS such as MySQL. In this case the associative array will be parsed and the query built such that the key is the column name and the value is what you want to query on. However, if you chose to use a NoSQL key/value store such as Memcache then the associative array is sorted and imploded to create a single string as the key.</p>
<p>Since we always specify the key as an associative array, switching between different data stores is as simple as changing the Class name from say MCache to SQLCache in your code. Nothing else is required to change data stores. Keys, expiration dates, and data processing all stay the same and all functions are called with the same arguments. This functionality is attributed to the abstract base Cache class which guides and regulates the inheriting classes.</p>
<p>Lets get to some examples:</p>
<p>In the following example we create a new SQLCache object and pass it our associative array of keys and values. Check if there is cached data, if there isnt then do something to generate the data and then cache it. Notice how you dont have to pass the key in again when setting the cache. The key is stored within the object so you can get and set as many times as you need without having to set the key every time. Lastly we delete the cache.</p>
<pre class="php"><span style="color: #808080; font-style: italic;">// Get Cache</span>
<span style="color: #0000ff;">$cache</span> = <span style="color: #000000; font-weight: bold;">new</span> SQLCache<span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'column1'</span> =&gt; <span style="color: #cc66cc;">123</span>, <span style="color: #ff0000;">'column2'</span> =&gt; <span style="color: #ff0000;">'blah'</span>, … <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$output</span> = <span style="color: #0000ff;">$cache</span>-&gt;<span style="color: #006600;">getCache</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>!<span style="color: #0000ff;">$output</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #808080; font-style: italic;">// Do something to generate data</span>
  <span style="color: #0000ff;">$output</span> = <span style="color: #ff0000;">'some datas'</span>;
  <span style="color: #808080; font-style: italic;">// Set Cache</span>
  <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$cacheNow</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// Force a write to cache now</span>
    <span style="color: #0000ff;">$cache</span>-&gt;<span style="color: #006600;">setCache</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$output</span>, <span style="color: #ff0000;">'+1 day'</span>, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// Setting no time defaults to time() + 86400, one day from now.</span>
    <span style="color: #0000ff;">$cache</span>-&gt;<span style="color: #006600;">setCache</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$output</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<a style="text-decoration: none;" href="http://www.php.net/print"><span style="color: #000066;">print</span></a> <span style="color: #0000ff;">$output</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// Delete the cache</span>
<span style="color: #0000ff;">$cache</span>-&gt;<span style="color: #006600;">deleteCache</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p>If ever you needed to update this caching strategy to include Memcached the only change would be to change SQLCache to Mcache:</p>
<pre class="php"><span style="color: #0000ff;">$cache</span> = <span style="color: #000000; font-weight: bold;">new</span> SQLCache<span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'column1'</span> =&gt; <span style="color: #cc66cc;">123</span>, <span style="color: #ff0000;">'column2'</span> =&gt; <span style="color: #ff0000;">'blah'</span>, … <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
to
<span style="color: #0000ff;">$cache</span> = <span style="color: #000000; font-weight: bold;">new</span> MCache<span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'key1'</span> =&gt; <span style="color: #cc66cc;">123</span>, <span style="color: #ff0000;">'key2'</span> =&gt; <span style="color: #ff0000;">'blah'</span>, … <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p>The column and key names are arbitrary and may be set to anything you want to name it. For SQL caches make sure you create a <a title="Example Cache Table Schema" href="http://github.com/jleider/extensible-php-caching-library" target="_blank">cache table</a> that has the corresponding column names and that they are indexed optimally.</p>
<p>While I have only created classes for SQL (MySQL - since there is a LIMIT 1), Memcached and File based caching, the base class can be extended to include any key/value store or any database with columns (MongoDB, CouchDB, Tokyo, Postgress, Oracle, etc). Just update the back end calls and you are good to go.</p>
<p>For anyone who updates or adds functionality please let me know so I can give credit where credit is due. This library is available under the <a title="GNU Lesser General Public License" href="http://www.gnu.org/licenses/lgpl.html" target="_blank">LGPLv3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2010/04/23/extensible-php-caching-library/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>ActiveRecord and Zend_Paginator_Adapter_Interface</title>
		<link>http://www.derivante.com/2009/10/29/activerecord-and-zend_paginator_adapter_interface/</link>
		<comments>http://www.derivante.com/2009/10/29/activerecord-and-zend_paginator_adapter_interface/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 14:29:07 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=757</guid>
		<description><![CDATA[Zend has a lot of tools to help speed up the application development process.  One such tool I found useful, was Paginator.   I am using php-activerecord in my project using Zend_Framework as the backend, to tie the two together is (&#8230;)</p><p><a href="http://www.derivante.com/2009/10/29/activerecord-and-zend_paginator_adapter_interface/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Zend has a lot of tools to help speed up the application development process.  One such tool I found useful, was Paginator.   I am using <a href="http://www.phpactiverecord.org" target="_blank">php-activerecord</a> in my project using Zend_Framework as the backend, to tie the two together is very simple.  Paginator requires two methods, it needs to be able to pull a count to get the total and it also needs to be able to pull in a subset of the data.  Take a look at the following example:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> My_Paginator implements Zend_Paginator_Adapter_Interface <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$table</span>,<span style="color: #0000ff;">$conditions</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>!<a style="text-decoration: none;" href="http://www.php.net/is_array"><span style="color: #000066;">is_array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$conditions</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
			<span style="color: #0000ff;">$conditions</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$conditions</span> <span style="color: #66cc66;">&#41;</span>;
&nbsp;
		<span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">conditions</span> = <span style="color: #0000ff;">$conditions</span>;
&nbsp;
		<span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">table</span>	  = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0000ff;">$table</span>;
&nbsp;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getItems<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$offset</span>, <span style="color: #0000ff;">$itemCountPerPage</span><span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">table</span>-&gt;<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'all'</span>, <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'limit'</span> =&gt; <span style="color: #0000ff;">$itemCountPerPage</span>, <span style="color: #ff0000;">'offset'</span> =&gt; <span style="color: #0000ff;">$offset</span>, <span style="color: #ff0000;">'conditions'</span> =&gt; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">conditions</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">table</span>-&gt;<span style="color: #006600;">count</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'conditions'</span> =&gt; <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">conditions</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;</pre>
<p>The two methods the Zend_Paginator_Adapter_Interface expects are count() and getItems().  The above example is a little "raw", it should serve to guide you in what to do when extending the Paginator with it's own adapter regardless of what your database layer is.  In the case of $conditions, these are the parameters you are passing to SQL:</p>
<pre class="php">&nbsp;
<span style="color: #0000ff;">$paginator</span> = <span style="color: #000000; font-weight: bold;">new</span> Zend_Paginator<span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> My_Paginator<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'User'</span>,<span style="color: #ff0000;">' active = &quot;Y&quot; '</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p>We want to access the User model, and only want to pull out users who are active.  Easy enough, you can certainly put in more complicated SQL here, but for a general use purpose it solves 99% of what I want with ActiveRecord and paging, pass in a model to the adapter, and some basic conditions for listing.</p>
<pre class="php">&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> pageUserAction<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
 		<span style="color: #0000ff;">$paginator</span> = <span style="color: #000000; font-weight: bold;">new</span> Zend_Paginator<span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> My_Paginator<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'User'</span>,<span style="color: #ff0000;">' active = &quot;Y&quot; '</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #0000ff;">$paginator</span>-&gt;<span style="color: #006600;">setCurrentPageNumber</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;_getParam<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'page'</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #0000ff;">$paginator</span>-&gt;<span style="color: #006600;">setItemCountPerPage</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'25'</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">view</span>-&gt;<span style="color: #006600;">paginator</span> = <span style="color: #0000ff;">$paginator</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>This is a basic usage of Zend_Paginator, you are passing in the current page you are on, and the results per page and pushing it out to the view, and on the view side:</p>
<pre class="php">&nbsp;
&lt;div id=<span style="color: #ff0000;">&quot;userlist&quot;</span>&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">paginator</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
	<span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">paginator</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$user</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
		<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">username</span>.<span style="color: #ff0000;">&quot;&lt;br&gt;&quot;</span>;
	<span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/div&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?</span>= <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">paginationControl</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">paginator</span>, <span style="color: #ff0000;">'Elastic'</span>, <span style="color: #ff0000;">'/common/paginator.phtml'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;</pre>
<p>If anyone has any problems or questions getting the two to work together let me know in the comments and I will do my best to answer your questions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/10/29/activerecord-and-zend_paginator_adapter_interface/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PHP Content Rating / Confidence</title>
		<link>http://www.derivante.com/2009/09/01/php-content-rating-confidence/</link>
		<comments>http://www.derivante.com/2009/09/01/php-content-rating-confidence/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 21:15:51 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[content analysis]]></category>
		<category><![CDATA[rating]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=717</guid>
		<description><![CDATA[For those web masters dealing with user feedback looking to weight content finding the right algorithm can be challenging. From experience, there is going to be no out of the box solution since each site and the requirements will be (&#8230;)</p><p><a href="http://www.derivante.com/2009/09/01/php-content-rating-confidence/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>For those web masters dealing with user feedback looking to weight content finding the right algorithm can be challenging. From experience, there is going to be no out of the box solution since each site and the requirements will be unique.  Getting started and putting a solid foundation is the first step and of course, refining over time to get just the right recipe. The following is a binomial proportion confidence interval (what?).  It is a PHP implementation using the Wilson Score Interval to weight the feedback.</p>
<p><span id="more-717"></span></p>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Rating
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> ratingAverage<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$positive</span>, <span style="color: #0000ff;">$total</span>, <span style="color: #0000ff;">$power</span> = <span style="color: #ff0000;">'0.05'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$total</span> == <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0</span>;
&nbsp;
    <span style="color: #0000ff;">$z</span> = Rating::<span style="color: #006600;">pnormaldist</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>-<span style="color: #0000ff;">$power</span>/<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$p</span> = <span style="color: #cc66cc;">1.0</span> * <span style="color: #0000ff;">$positive</span> / <span style="color: #0000ff;">$total</span>;
    <span style="color: #0000ff;">$s</span> = <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$p</span> + <span style="color: #0000ff;">$z</span>*<span style="color: #0000ff;">$z</span>/<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span>*<span style="color: #0000ff;">$total</span><span style="color: #66cc66;">&#41;</span> - <span style="color: #0000ff;">$z</span> * <a style="text-decoration: none;" href="http://www.php.net/sqrt"><span style="color: #000066;">sqrt</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$p</span>*<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>-<span style="color: #0000ff;">$p</span><span style="color: #66cc66;">&#41;</span>+<span style="color: #0000ff;">$z</span>*<span style="color: #0000ff;">$z</span>/<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span>*<span style="color: #0000ff;">$total</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>/<span style="color: #0000ff;">$total</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>/<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>+<span style="color: #0000ff;">$z</span>*<span style="color: #0000ff;">$z</span>/<span style="color: #0000ff;">$total</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$s</span>;
  <span style="color: #66cc66;">&#125;</span> 
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> pnormaldist<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$qn</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$b</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
      <span style="color: #cc66cc;">1.570796288</span>, <span style="color: #cc66cc;">0.03706987906</span>, <span style="color: #cc66cc;">-0</span>.8364353589e<span style="color: #cc66cc;">-3</span>,
      <span style="color: #cc66cc;">-0</span>.2250947176e<span style="color: #cc66cc;">-3</span>, <span style="color: #cc66cc;">0</span>.6841218299e<span style="color: #cc66cc;">-5</span>, <span style="color: #cc66cc;">0</span>.5824238515e<span style="color: #cc66cc;">-5</span>,
      <span style="color: #cc66cc;">-0</span>.104527497e<span style="color: #cc66cc;">-5</span>, <span style="color: #cc66cc;">0</span>.8360937017e<span style="color: #cc66cc;">-7</span>, <span style="color: #cc66cc;">-0</span>.3231081277e<span style="color: #cc66cc;">-8</span>,
      <span style="color: #cc66cc;">0</span>.3657763036e<span style="color: #cc66cc;">-10</span>, <span style="color: #cc66cc;">0</span>.6936233982e<span style="color: #cc66cc;">-12</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$qn</span> &lt; <span style="color: #cc66cc;">0.0</span> || <span style="color: #cc66cc;">1.0</span> &lt; <span style="color: #0000ff;">$qn</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0.0</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$qn</span> == <span style="color: #cc66cc;">0.5</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0.0</span>;
&nbsp;
    <span style="color: #0000ff;">$w1</span> = <span style="color: #0000ff;">$qn</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$qn</span> &gt; <span style="color: #cc66cc;">0.5</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #0000ff;">$w1</span> = <span style="color: #cc66cc;">1.0</span> - <span style="color: #0000ff;">$w1</span>;
&nbsp;
    <span style="color: #0000ff;">$w3</span> = - <a style="text-decoration: none;" href="http://www.php.net/log"><span style="color: #000066;">log</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4.0</span> * <span style="color: #0000ff;">$w1</span> * <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1.0</span> - <span style="color: #0000ff;">$w1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$w1</span> = <span style="color: #0000ff;">$b</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>;
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span> = <span style="color: #cc66cc;">1</span>;<span style="color: #0000ff;">$i</span> &lt;= <span style="color: #cc66cc;">10</span>; <span style="color: #0000ff;">$i</span>++<span style="color: #66cc66;">&#41;</span>
      <span style="color: #0000ff;">$w1</span> += <span style="color: #0000ff;">$b</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$i</span><span style="color: #66cc66;">&#93;</span> * <a style="text-decoration: none;" href="http://www.php.net/pow"><span style="color: #000066;">pow</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$w3</span>,<span style="color: #0000ff;">$i</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$qn</span> &gt; <span style="color: #cc66cc;">0.5</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">return</span> <a style="text-decoration: none;" href="http://www.php.net/sqrt"><span style="color: #000066;">sqrt</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$w1</span> * <span style="color: #0000ff;">$w3</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #b1b100;">return</span> - <a style="text-decoration: none;" href="http://www.php.net/sqrt"><span style="color: #000066;">sqrt</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$w1</span> * <span style="color: #0000ff;">$w3</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>The function takes 3 parameters: the positive votes, total votes, and the power. The power can be adjusted, 0.10 to have a 95% chance that your lower bound is correct, 0.05 to have a 97.5% chance, etc.  Sample usage:</p>
<pre class="php">sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span>,<span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">250</span>,<span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1000</span>,<span style="color: #cc66cc;">500</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> sample<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$p</span>,<span style="color: #0000ff;">$n</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> Rating::<span style="color: #006600;">ratingAverage</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$p</span>,<span style="color: #0000ff;">$p</span>+<span style="color: #0000ff;">$n</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>Output:</p>
<table border="0" cellpadding="2" cellspacing="0" border="1">
<tbody>
<tr>
<td>Positive</td>
<td>Negative</td>
<td>Score</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0.20654931654388</td>
</tr>
<tr>
<td>100</td>
<td>50</td>
<td>0.58789756740385</td>
</tr>
<tr>
<td>250</td>
<td>100</td>
<td>0.6648317184611</td>
</tr>
<tr>
<td>1000</td>
<td>500</td>
<td>0.6424116916199</td>
</tr>
</tbody>
</table>
<p>When dealing with sites like Reddit, Digg, and the like  you have a certain "freshness" element.  The above solution might be a working model for the entire span of the site, but for that front page element you will need to implement some form of "gravity".  This can be done by taking the raw score and decaying it over time, like so:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Rating
<span style="color: #66cc66;">&#123;</span>
  ...
  <span style="color: #000000; font-weight: bold;">public</span> <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> gravityRating<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$positive</span>, <span style="color: #0000ff;">$total</span>, <span style="color: #0000ff;">$time</span>, <span style="color: #0000ff;">$power</span> = <span style="color: #ff0000;">'0.05'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$total</span> == <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #66cc66;">&#40;</span>Rating::<span style="color: #006600;">ratingAverage</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$positive</span>, <span style="color: #0000ff;">$total</span>, <span style="color: #0000ff;">$power</span><span style="color: #66cc66;">&#41;</span> / <a style="text-decoration: none;" href="http://www.php.net/pow"><span style="color: #000066;">pow</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$time</span>,<span style="color: #cc66cc;">0.5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
  ...
<span style="color: #66cc66;">&#125;</span>
&nbsp;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span>,<span style="color: #cc66cc;">50</span>,<span style="color: #ff0000;">'0.5'</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span>,<span style="color: #cc66cc;">50</span>,<span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span>,<span style="color: #cc66cc;">50</span>,<span style="color: #ff0000;">'4'</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span>,<span style="color: #cc66cc;">50</span>,<span style="color: #ff0000;">'8'</span><span style="color: #66cc66;">&#41;</span>;
sample<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span>,<span style="color: #cc66cc;">50</span>,<span style="color: #ff0000;">'24'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> sample<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$p</span>,<span style="color: #0000ff;">$n</span>,<span style="color: #0000ff;">$time</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> Rating::<span style="color: #006600;">gravityRating</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$p</span>,<span style="color: #0000ff;">$p</span>+<span style="color: #0000ff;">$n</span>,<span style="color: #0000ff;">$time</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>In the example above, $time represents the age (in hours) and you can see the decay in the output:</p>
<p>0.83141271310867<br />
0.58789756740385<br />
0.29394878370192<br />
0.20785317827717<br />
0.12000408843024</p>
<p>My recommendation would be to "cap" the time to stop decay after a fixed period such as 12 or 24 hours to stop the initial boost of fresh content and let it normalize quickly.  The rate of decay of course, can be adjusted as fast or as slow as you want and again the individual weighting you want to apply will vary from site to site.  Depending on the volatility of your content, a front page "freshness" that will encompass a week would not merit a 12 hour decay, but rather a week long decay.   Hopefully the above code is enough to get started with content rating and making better use of user feedback and can help lead web masters to making a more intelligent calculation of their content beyond the traditional "5-Star Rating".</p>
<p>[ c9maji2tvz ]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/09/01/php-content-rating-confidence/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>PHP Google Analytics API</title>
		<link>http://www.derivante.com/2009/07/08/php-google-analytics-api/</link>
		<comments>http://www.derivante.com/2009/07/08/php-google-analytics-api/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 15:19:50 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[Analytics]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=707</guid>
		<description><![CDATA[GAPI 1.3 released this past month. First, read the Google Analytics Data API Reference and then read up on dimensions, metrics, and valid combinations of the two.  The quotas apply to a single web property, so each analytics profile (site1, (&#8230;)</p><p><a href="http://www.derivante.com/2009/07/08/php-google-analytics-api/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/p/gapi-google-analytics-php-interface/">GAPI 1.3</a> released this past month.  First, read the <a href="http://code.google.com/apis/analytics/docs/gdata/gdataReference.html">Google Analytics Data API Reference</a> and then read up on <a href="http://code.google.com/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html">dimensions, metrics, and valid combinations</a> of the two.  The quotas apply to a single web property, so each analytics profile (site1, site2, etc) are subject to their own individual quotas.   There is no per user account limit for accessing the API.    If you plan on making any kind of on demand application I suggest you query in bulk and cache the results locally (analytics is not real time anyways).</p>
<p><span id="more-707"></span></p>
<p><strong>API Features</strong></p>
<ul>
<li>Supports CURL and fopen HTTP access methods, with autodetection </li>
<li>PHP arrays for Google Analytics metrics and dimensions </li>
<li>Account data object mapping - get methods for parameters </li>
<li>Report data object mapping - get methods for metrics and parameters </li>
<li>Easy filtering, use a GAPI query language for Google Analytics filters </li>
<li>Full PHP5 Object Oriented code, ready for use in your PHP application </li>
</ul>
<p><br></p>
<p><strong>Google Quotas</strong></p>
<ul>
<li>The quota applies to a <em>single web property</em></li>
<li>10,000 requests per 24 hours</li>
<li>100 requests in any given 10-second period</li>
<li>A query is also limited to pagination limits of 10,000 entries per feed,   with a default response of 1,000 entries</li>
</ul>
<p><br></p>
<p>While the broad set of data they have is extremely useful to pull down to do your own processing on, I find the custom visitor segments with the API a lot more interesting.    If you have a user based site with registration and collect information on your users, you can pull this data back out to determine a lot of information about your user.   A lot of tools are already built into Analytics for reporting but the ability to mash this data up to provide custom reporting for your users (customers) without giving them access to analytics is key to delivering metrics and performance</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/07/08/php-google-analytics-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SOLR Filtering Performance Increase</title>
		<link>http://www.derivante.com/2009/06/23/solr-filtering-performance-increase/</link>
		<comments>http://www.derivante.com/2009/06/23/solr-filtering-performance-increase/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 15:55:44 +0000</pubDate>
		<dc:creator>Justin Leider</dc:creator>
				<category><![CDATA[SOLR]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=689</guid>
		<description><![CDATA[A couple months ago I wrote about the terrible performance and a work around for SOLR / Lucene search engine. I discovered that performance would drop off a cliff while using filter queries to narrow search results for search queries (&#8230;)</p><p><a href="http://www.derivante.com/2009/06/23/solr-filtering-performance-increase/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>A couple months ago I wrote about the <a title="100x Increase in SOLR Performance and Throughput" href="http://www.derivante.com/2009/04/27/100x-increase-in-solr-performance-and-throughput/">terrible performance and a work around</a> for SOLR / Lucene search engine. I discovered that performance would drop off a cliff while using filter queries to narrow search results for search queries on common terms in large indexes.  Although, it looks like the issue has been addressed in some of the latest nightly <a title="SOLR Search Engine" href="http://lucene.apache.org/solr/" target="_blank">SOLR</a> builds and is scheduled for official release with SOLR v1.4. Previous to this new version the filter queries were applied after the main query ran. This is all well and good but it doesn't help speed your query up like you think it should. The new version <a href="http://www.lucidimagination.com/blog/2009/05/27/filtered-query-performance-increases-for-solr-14/" target="_blank">applies the filters in parallel</a> to the main query significantly speeding up searches with common queries and query filters by 30% to 80% along with a 40% smaller memory footprint.</p>
<p>However, even with this speed improvement you still should consider how you structure your queries. There is no need to do a query across every field if you know you really want to filter everything down with a single filter query. Try moving that filter query (fq) into the actual query (q) as <field>:<filter>. You might be <a title="100x Increase in SOLR Performance and Throughput" href="http://www.derivante.com/2009/04/27/100x-increase-in-solr-performance-and-throughput/">surprised by the results</a>...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/06/23/solr-filtering-performance-increase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Rapid Application Development with ZF1.8 and AR</title>
		<link>http://www.derivante.com/2009/05/21/php-rapid-application-development-with-zf18-and-ar/</link>
		<comments>http://www.derivante.com/2009/05/21/php-rapid-application-development-with-zf18-and-ar/#comments</comments>
		<pubDate>Thu, 21 May 2009 19:02:42 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[Framework]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[php 5.3]]></category>
		<category><![CDATA[phpactiverecord]]></category>
		<category><![CDATA[ZendFramework]]></category>
		<category><![CDATA[Zend_Tool]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=627</guid>
		<description><![CDATA[In the days since I began programming in PHP the web has come a long way. With the 5.3 release of PHP, the OOP side of things are finally getting a much needed polish. In the past year there's been (&#8230;)</p><p><a href="http://www.derivante.com/2009/05/21/php-rapid-application-development-with-zf18-and-ar/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>In the days since I began programming in PHP the web has come a long way.  With the 5.3 release of PHP, the OOP side of things are finally getting a much needed polish.  In the past year there's been a steady rise in the usage of Ruby on Rails for web development as programmers are discovering that coming up with an idea for a site is far more enjoyable than programming one.  Rails offers a very rapid application development environment to get from concept to code in a minimal number of steps.  Unfortunately, PHP has been lacking in this regard. PHP needs a standard framework and easy database interaction. Currently, the steps required to go from concept to code brings with it a huge overhead in scaffolding development.</p>
<p><span id="more-627"></span></p>
<p>It is precisely this overhead that needs to be eliminated.  Time is money and if you are working with a new application on a weekly or monthly basis the scaffolding overhead comprises a great deal of that time.  Not to mention that most web applications today are running to and fro from a database. This time spent fetching and storing data makes up for a significant chunk in the overall development.  2009 is a big step forward for PHP and there are tools out there that tackle this problem.</p>
<p>
Enter ZendFramework 1.8, just recently released it represents Zend's commitment to make PHP a competitive environment for Rapid Application Development (totally RAD).  There are several new tools included within this release, primarily Zend_Tool, Zend_Application, and Zend_Navigation. Zend_Tool_Project allows for the automated creation of new projects complete with a ready to go application shell.  You can liken this shell to a new Hello World! project with the core structure and scaffolding setup.  Rather than going into the details of everything included within the release, you can find a thorough overview within the 1.8 release notes.</p>
<p>This brings me to what I'm really excited about. Recently we pushed out <a href="http://www.derivante.com/2009/05/14/php-activerecord-with-php-53/">PHP ActiveRecord</a> for everyone!  This tutorial goes over the steps necessary to build your environment.  You'll be able to create new projects within the ZendFramework with <a href="http://www.derivante.com/2009/05/14/php-activerecord-with-php-53/">PHP ActiveRecord</a>. I believe developers should spend their time dealing with application logic and not be burdened with configuration, bootstrapping or custom SQL.  For this tutorial I am using the following environment:</p>
<p>- Ubuntu 9.04<br />
- PHP 5.3-RC1<br />
- MySQL 5.4<br />
- Apache 2.2.11<br />
- ZendFramework 1.8 min<br />
- php-activerecord 0.9</p>
<p>For the sake of keeping this tutorial short and concise, there are already several resources out there that deal with compiling PHP 5.3.  I'll assume you've already setup your server with MySQL, PHP and Apache ready to go.  In fact, you can use nginx if you prefer going down that route or even ZendServer CE, although I personally prefer Apache. It certainly doesn't matter what you're serving out PHP with and it will probably be dependent on what you're existing environment is using.</p>
<p><strong>Installing ZendFramework 1.8 and ActiveRecord</strong></p>
<p>We're going to want both libraries in our PHP include directory.  First you should download the latest ZF release, 1.8.1 at the time of this post.   When you have it ready to go on your server it is important to make sure your environment is working.  If you installed PHP 5.3 correctly you should be able to get the following output from CLI:</p>
<pre># php -v
PHP 5.3.0RC1 (cli) (built: May  3 2009 15:31:21)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
# php -i | grep include_path
include_path => .:/usr/local/php/lib => .:/usr/local/php/lib</pre>
<p>Don't worry if your include path is elsewhere, just make a note of where it is since we'll be dumping the Zend stuff there. Now to extract and install Zend:</p>
<pre># tar xzfv ZendFramework-1.8.1-minimal.tar.gz
# mv ZendFramework-1.8.1-minimal/library/Zend /usr/local/php/lib/
# mv ZendFramework-1.8.1-minimal/bin/zf.* /usr/local/php/bin/
# ln -s /usr/local/php/bin/zf.sh /usr/bin/zf
# zf show version
Zend Framework Version: 1.8.1</pre>
<p>I opted to put the zf.sh into my PHP bin directory and symlink it from my bin dir.  The next step is to download the source from <a href="http://github.com/kla/php-activerecord/">github</a> and unpack it into your include path to a directory called php-activerecord. Our dependencies are there and we can move on to our first project.</strong></p>
<p><strong>Create Project</strong></p>
<p>Now that everything is installed, we want to test out zf create project.  The following example is a bare bones project ready for us to extend:</p>
<pre># zf create project /var/www/newproject
Creating project at /var/www/newproject
# ls /var/www/newproject/
application  library  public  tests</pre>
<p>That is it, you are ready for the web.  Configure your web server to start serving out pages from the location you set for your new project.  The docroot path should be /var/www/newproject/public.  Load up your web browser and you should see your page.</p>
<p><strong>Loading up ActiveRecord</strong></p>
<p>Inside your application/Bootstrap.php you might notice the code rather bare.  The Zend Bootstrapper will load anything within the bootstrap function starting with _init*.  To tack on ActiveRecord, we simply add the following:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Bootstrap <span style="color: #000000; font-weight: bold;">extends</span> Zend_Application_Bootstrap_Bootstrap
<span style="color: #66cc66;">&#123;</span>
    protected <span style="color: #000000; font-weight: bold;">function</span> _initActiveRecord<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #b1b100;">require_once</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;php-activerecord/ActiveRecord.php&quot;</span><span style="color: #66cc66;">&#41;</span>;
        ActiveRecord\Config::<span style="color: #006600;">initialize</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$cfg</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_model_directory</span><span style="color: #66cc66;">&#40;</span>APPLICATION_PATH . <span style="color: #ff0000;">'/models'</span> <span style="color: #66cc66;">&#41;</span>;
            <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_connections</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
                <span style="color: #ff0000;">'development'</span> =&gt; <span style="color: #ff0000;">'mysql://user:password@localhost/newproject'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p>You will need to adjust your SQL connect strings, and at this point if you want to restructure your model directory differently you may do so.  There are only two configuration points, both of which you could pass from an XML or INI config.  Even though ActiveRecord is loaded, we still need to test out that everything is working. In order to do this we will need to create some test data:</p>
<pre class="sql"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">DATABASE</span> newproject;
<span style="color: #993333; font-weight: bold;">USE</span> newproject;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> books<span style="color: #66cc66;">&#40;</span>
    id int <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>,
    name varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span>,
    author varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> books<span style="color: #66cc66;">&#40;</span>id,name,author<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #ff0000;">'How to be Angry'</span>,<span style="color: #ff0000;">'Jax'</span><span style="color: #66cc66;">&#41;</span>;</pre>
<p>The next step is to create a model for the books table to be used from within your application. In your model directory that you set within the configuration above, create a Book.php with the following:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model <span style="color: #66cc66;">&#123;</span> <span style="color: #66cc66;">&#125;</span></pre>
<p>And finally to test out that everything is working, within your IndexController.php for indexAction add the following:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> indexAction<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">view</span>-&gt;<span style="color: #006600;">book</span> = Book::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>
<p>And so we can actually see the output, edit your /views/scripts/index/index.phtml with the following:</p>
<pre class="php">Today I read <span style="color: #000000; font-weight: bold;">&lt;?</span>=book-&gt;<span style="color: #006600;">name</span>?&gt; by <span style="color: #000000; font-weight: bold;">&lt;?</span>=book-&gt;<span style="color: #006600;">author</span>?&gt; and it was terrible.</pre>
<p>As you can see, you can pull the variable set by the action assigned to the view or you can query right from the view itself if you please.  If you get the following output, everything is good to go:</p>
<pre>Today I read How to be Angry by Jax and it was terrible.</pre>
<p><strong>Next Steps</strong></p>
<p>Going forward, there is plenty of room to extend this setup.  Unfortunately, the Zend_Tool_Project abstraction documents are still being completed but there are examples out there on how to add new commands to it.  One new command I am working on is the automated creation of AR models by passing a database connect string to simplify the process even further.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/05/21/php-rapid-application-development-with-zf18-and-ar/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>PHP ActiveRecord Available for Beta Testing</title>
		<link>http://www.derivante.com/2009/05/19/php-activerecord-available-for-beta-testing/</link>
		<comments>http://www.derivante.com/2009/05/19/php-activerecord-available-for-beta-testing/#comments</comments>
		<pubDate>Wed, 20 May 2009 01:09:27 +0000</pubDate>
		<dc:creator>Kien La</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[php 5.3]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=548</guid>
		<description><![CDATA[We've been working hard to get this ready for people to start poking around in and we're happy to announce that it's now ready for public beta testing! You can grab it from http://github.com/kla/php-activerecord/. Play with it... break it... and (&#8230;)</p><p><a href="http://www.derivante.com/2009/05/19/php-activerecord-available-for-beta-testing/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>We've been working hard to get this ready for people to start poking around in and we're happy to announce that it's now ready for public beta testing! You can grab it from <a href="http://github.com/kla/php-activerecord/">http://github.com/kla/php-activerecord/</a>. Play with it... break it... and give us your feedback to help us make a better library for everyone! We want to hear from you.</p>
<p><span id="more-548"></span></p>
<h2>Quick Start</h2>
<p>We'll start first with a bare bones example to show how little you need to get up and running. There's <i>very</i> little to configure. We've adhered to the convention over configuration philosophy so there are no code generators you need to run and no xml/yaml mapping files to maintain.</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #808080; font-style: italic;">// make sure the ActiveRecord project is in your current directory</span>
<span style="color: #808080; font-style: italic;">// or your include_path</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #ff0000;">'ActiveRecord/ActiveRecord.php'</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// assumes a table name of &quot;books&quot; with a primay key named &quot;id&quot;</span>
<span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model <span style="color: #66cc66;">&#123;</span> <span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">// initialize ActiveRecord</span>
ActiveRecord\Config::<span style="color: #006600;">initialize</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$cfg</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_model_directory</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'.'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_connections</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <span style="color: #ff0000;">'development'</span> =&gt; <span style="color: #ff0000;">'mysql://username:password@localhost/database_name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<a style="text-decoration: none;" href="http://www.php.net/print_r"><span style="color: #000066;">print_r</span></a><span style="color: #66cc66;">&#40;</span>Book::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>-&gt;<span style="color: #006600;">attributes</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>
<p>That's it! The code for this is located in the examples/simple directory. You can run it with "php examples/simple/simple.php". Make sure to modify the connection string to suit your system and run the simple.sql script appropriately.</p>
<h2>Serious Business Time</h2>
<p>Now for a not so completely trivial example. This example will simulate a very dumb ordering and payment model. See the examples/orders directory for the source. You can run this sample by executing "php examples/orders/orders.php". Again, make sure you modify the connection string to suit your system and be sure the schema in orders.sql has been created in your test database.</p>
<p>First, let's look at the models:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Person <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// a person can have many orders and payments</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$has_many</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'orders'</span><span style="color: #66cc66;">&#41;</span>,
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'payments'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// must have a name and a state which has a custom error message</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_presence_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'name'</span><span style="color: #66cc66;">&#41;</span>, <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'state'</span>, <span style="color: #ff0000;">'message'</span> =&gt; <span style="color: #ff0000;">'Where do you live then?'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Order <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// order belongs to a person</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$belongs_to</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'person'</span><span style="color: #66cc66;">&#41;</span>,
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'order'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// order can have many payments by many people</span>
    <span style="color: #808080; font-style: italic;">// the conditions is just there as an example as it makes no logical sense</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$has_many</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'payments'</span><span style="color: #66cc66;">&#41;</span>,
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'people'</span>,
            <span style="color: #ff0000;">'through'</span>    =&gt; <span style="color: #ff0000;">'payments'</span>,
            <span style="color: #ff0000;">'select'</span>     =&gt; <span style="color: #ff0000;">'people.*, payments.amount'</span>,
            <span style="color: #ff0000;">'conditions'</span> =&gt; <span style="color: #ff0000;">'payments.amount &lt; 200'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// order must have a price and tax &gt; 0</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_numericality_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'price'</span>, <span style="color: #ff0000;">'greater_than'</span> =&gt; <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>,
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'tax'</span>,   <span style="color: #ff0000;">'greater_than'</span> =&gt; <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// setup a callback to automatically apply a tax</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_validation_on_create</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'apply_tax'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> apply_tax<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">person</span>-&gt;<span style="color: #006600;">state</span> == <span style="color: #ff0000;">'VA'</span><span style="color: #66cc66;">&#41;</span>
            <span style="color: #0000ff;">$tax</span> = <span style="color: #cc66cc;">0.045</span>;
        <span style="color: #b1b100;">elseif</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">person</span>-&gt;<span style="color: #006600;">state</span> == <span style="color: #ff0000;">'CA'</span><span style="color: #66cc66;">&#41;</span>
            <span style="color: #0000ff;">$tax</span> = <span style="color: #cc66cc;">0.10</span>;
        <span style="color: #b1b100;">else</span>
            <span style="color: #0000ff;">$tax</span> = <span style="color: #cc66cc;">0.02</span>;
&nbsp;
        <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">tax</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">price</span> * <span style="color: #0000ff;">$tax</span>;
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Payment <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// payment belongs to a person</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$belongs_to</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'person'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>
<p>And here's the code that does everything:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #b1b100;">require_once</span> <a style="text-decoration: none;" href="http://www.php.net/dirname"><span style="color: #000066;">dirname</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">'/../../ActiveRecord.php'</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// initialize ActiveRecord</span>
ActiveRecord\Config::<span style="color: #006600;">initialize</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$cfg</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_model_directory</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/dirname"><span style="color: #000066;">dirname</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">'/models'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_connections</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
        <span style="color: #ff0000;">'development'</span> =&gt; <span style="color: #ff0000;">'mysql://test:test@127.0.0.1/orders_test'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// you can change the default connection with the below</span>
    <span style="color: #808080; font-style: italic;">//$cfg-&gt;set_default_connection('production');</span>
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// create some people</span>
<span style="color: #0000ff;">$jax</span> = <span style="color: #000000; font-weight: bold;">new</span> Person<span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'name'</span> =&gt; <span style="color: #ff0000;">'Jax'</span>, <span style="color: #ff0000;">'state'</span> =&gt; <span style="color: #ff0000;">'CA'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$jax</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// compact way to create and save a model</span>
<span style="color: #0000ff;">$tito</span> = Person::<span style="color: #006600;">create</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'name'</span> =&gt; <span style="color: #ff0000;">'Tito'</span>, <span style="color: #ff0000;">'state'</span> =&gt; <span style="color: #ff0000;">'VA'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// place orders. tax is automatically applied in a callback</span>
<span style="color: #808080; font-style: italic;">// create_orders will automatically place the created model into $tito-&gt;orders</span>
<span style="color: #808080; font-style: italic;">// even if it failed validation</span>
<span style="color: #0000ff;">$pokemon</span> = <span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">create_orders</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'item_name'</span> =&gt; <span style="color: #ff0000;">'Live Pokemon'</span>, <span style="color: #ff0000;">'price'</span> =&gt; <span style="color: #cc66cc;">6999.99</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$coal</span>    = <span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">create_orders</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'item_name'</span> =&gt; <span style="color: #ff0000;">'Lump of Coal'</span>, <span style="color: #ff0000;">'price'</span> =&gt; <span style="color: #cc66cc;">100.00</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$freebie</span> = <span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">create_orders</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'item_name'</span> =&gt; <span style="color: #ff0000;">'Freebie'</span>, <span style="color: #ff0000;">'price'</span> =&gt; <span style="color: #cc66cc;">-100.99</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$freebie</span>-&gt;<span style="color: #006600;">errors</span><span style="color: #66cc66;">&#41;</span> &gt; <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;[FAILED] saving order $freebie-&gt;item_name: &quot;</span> .
        <a style="text-decoration: none;" href="http://www.php.net/join"><span style="color: #000066;">join</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">','</span>,<span style="color: #0000ff;">$freebie</span>-&gt;<span style="color: #006600;">errors</span>-&gt;<span style="color: #006600;">full_messages</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">// payments</span>
<span style="color: #0000ff;">$pokemon</span>-&gt;<span style="color: #006600;">create_payments</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'amount'</span> =&gt; <span style="color: #cc66cc;">1.99</span>, <span style="color: #ff0000;">'person_id'</span> =&gt; <span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$pokemon</span>-&gt;<span style="color: #006600;">create_payments</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'amount'</span> =&gt; <span style="color: #cc66cc;">4999.50</span>, <span style="color: #ff0000;">'person_id'</span> =&gt; <span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$pokemon</span>-&gt;<span style="color: #006600;">create_payments</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'amount'</span> =&gt; <span style="color: #cc66cc;">2.50</span>, <span style="color: #ff0000;">'person_id'</span> =&gt; <span style="color: #0000ff;">$jax</span>-&gt;<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// reload since we don't want the freebie to show up (because it failed validation)</span>
<span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">reload</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;$tito-&gt;name has &quot;</span> . <a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">orders</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot; orders for: &quot;</span> .
    <a style="text-decoration: none;" href="http://www.php.net/join"><span style="color: #000066;">join</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">', '</span>,ActiveRecord\collect<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">orders</span>,<span style="color: #ff0000;">'item_name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// get all orders placed by Tito</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span>Order::<span style="color: #006600;">find_all_by_person_id</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$order</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Order #$order-&gt;id for $order-&gt;item_name &quot;</span> .
        <span style="color: #ff0000;">&quot;($$order-&gt;price + $$order-&gt;tax tax) &quot;</span> .
        <span style="color: #ff0000;">&quot;ordered by &quot;</span> . <span style="color: #0000ff;">$order</span>-&gt;<span style="color: #006600;">person</span>-&gt;<span style="color: #006600;">name</span> . <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$order</span>-&gt;<span style="color: #006600;">payments</span><span style="color: #66cc66;">&#41;</span> &gt; <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #808080; font-style: italic;">// display each payment for this order</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$order</span>-&gt;<span style="color: #006600;">payments</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$payment</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
            <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;  payment #$payment-&gt;id of $$payment-&gt;amount by &quot;</span> .
            <span style="color: #0000ff;">$payment</span>-&gt;<span style="color: #006600;">person</span>-&gt;<span style="color: #006600;">name</span> . <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
    <span style="color: #b1b100;">else</span>
        <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;  no payments<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
    <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">// display summary of all payments made by Tito and Jax</span>
<span style="color: #0000ff;">$conditions</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'conditions'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'id IN(?)'</span>,<a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$tito</span>-&gt;<span style="color: #006600;">id</span>,<span style="color: #0000ff;">$jax</span>-&gt;<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,
    <span style="color: #ff0000;">'order'</span>      =&gt; <span style="color: #ff0000;">'name desc'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span>Person::<span style="color: #006600;">all</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$conditions</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$person</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$n</span> = <a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$person</span>-&gt;<span style="color: #006600;">payments</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$total</span> = <a style="text-decoration: none;" href="http://www.php.net/array_sum"><span style="color: #000066;">array_sum</span></a><span style="color: #66cc66;">&#40;</span>ActiveRecord\collect<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$person</span>-&gt;<span style="color: #006600;">payments</span>,<span style="color: #ff0000;">'amount'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;$person-&gt;name made $n payments for a total of $$total<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">// using order has_many people through payments with options</span>
<span style="color: #808080; font-style: italic;">//</span>
<span style="color: #808080; font-style: italic;">// array('people',</span>
<span style="color: #808080; font-style: italic;">//    'through' =&gt; 'payments',</span>
<span style="color: #808080; font-style: italic;">//    'select' =&gt; 'people.*, payments.amount',</span>
<span style="color: #808080; font-style: italic;">//    'conditions' =&gt; 'payments.amount &lt; 200'));</span>
<span style="color: #808080; font-style: italic;">//</span>
<span style="color: #808080; font-style: italic;">// this means our people in the loop below also has the payment information since</span>
<span style="color: #808080; font-style: italic;">// it is part of an inner join we will only see 2 of the people instead of 3</span>
<span style="color: #808080; font-style: italic;">// because 1 of the payments is greater than 200</span>
<span style="color: #0000ff;">$order</span> = Order::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$pokemon</span>-&gt;<span style="color: #006600;">id</span><span style="color: #66cc66;">&#41;</span>;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Order #$order-&gt;id for $order-&gt;item_name ($$order-&gt;price + $$order-&gt;tax tax)<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$order</span>-&gt;<span style="color: #006600;">people</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$person</span><span style="color: #66cc66;">&#41;</span>
    <a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;  payment of $$person-&gt;amount by &quot;</span> . <span style="color: #0000ff;">$person</span>-&gt;<span style="color: #006600;">name</span> . <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>
<p>The orders example should produce the following output:</p>
<pre>[FAILED] saving order Freebie: Price must be greater than 0, Tax must be greater than 0

Tito has 2 orders for: Live Pokemon, Lump of Coal

Order #3 for Live Pokemon ($6999.99 + $315 tax) ordered by Tito
  payment #4 of $1.99 by Tito
  payment #5 of $4999.5 by Tito
  payment #6 of $2.5 by Jax

Order #4 for Lump of Coal ($100 + $4.5 tax) ordered by Tito
  no payments

Tito made 2 payments for a total of $5001.49

Jax made 1 payments for a total of $2.5

Order #3 for Live Pokemon ($6999.99 + $315 tax)
  payment of $2.50 by Jax
  payment of $1.99 by Tito</pre>
<h2>EXTENDED CONFIGURATION</h2>
<p>Here's one more example that is basically the same as the first, but the point here is to display some of the ways to extend configuration (while remaining close to convention).</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">// explicit table name since our table is not &quot;books&quot;</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$table_name</span> = <span style="color: #ff0000;">'simple_book'</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// explicit pk since our pk is not &quot;id&quot;</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$primary_key</span> = <span style="color: #ff0000;">'book_id'</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// explicit connection name since we always want production with this model</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$connection</span> = <span style="color: #ff0000;">'production'</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// explicit database name will generate sql like so =&gt; db.table_name</span>
    <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$db</span> = <span style="color: #ff0000;">'test'</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">// ActiveRecord allows the use of multiple connections</span>
<span style="color: #0000ff;">$connections</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'development'</span> =&gt; <span style="color: #ff0000;">'mysql://test:test@127.0.0.1/development'</span>,
    <span style="color: #ff0000;">'production'</span> =&gt; <span style="color: #ff0000;">'mysql://test:test@127.0.0.1/production'</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// initialize ActiveRecord</span>
ActiveRecord\Config::<span style="color: #006600;">initialize</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$cfg</span><span style="color: #66cc66;">&#41;</span> use <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$connections</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_model_directory</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'.'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_connections</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$connections</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<a style="text-decoration: none;" href="http://www.php.net/print_r"><span style="color: #000066;">print_r</span></a><span style="color: #66cc66;">&#40;</span>Book::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>-&gt;<span style="color: #006600;">attributes</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<h2>Simplicity</h2>
<p>From the configuration, all the way to a <i>serious-business</i> example, ActiveRecord takes care of the heavy-lifting and the gritty details for you. This allows you, the developer, to focus more on business logic and complex code instead of composing custom SQL queries or designing ways to handle your data. Because we have embraced a convention over configuration philosophy, using our library is not painful. The conventions are easy to remember which will also contribute to stream-lining your productivity as a developer.</p>
<h2>Where can you find ActiveRecord?</h2>
<p>Again, the code is hosted on <a href="http://github.com/kla/php-activerecord/">http://github.com/kla/php-activerecord/</a>. We also have a <a href="http://www.phpactiverecord.org/">website</a> which will be available in the near future. We hope to have all the necessary content such as: tutorials, screencasts, and documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/05/19/php-activerecord-available-for-beta-testing/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>PHP ActiveRecord with PHP 5.3</title>
		<link>http://www.derivante.com/2009/05/14/php-activerecord-with-php-53/</link>
		<comments>http://www.derivante.com/2009/05/14/php-activerecord-with-php-53/#comments</comments>
		<pubDate>Thu, 14 May 2009 04:21:34 +0000</pubDate>
		<dc:creator>Jacques Fuentes</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[php 5.3]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=391</guid>
		<description><![CDATA[Update! Find the latest here. PHP 5.3 gets ActiveRecord! A quick search to find an implementation of active record for php on google is discouraging when one considers the state of ActiveRecord for Ruby on Rails. The reader will notice (&#8230;)</p><p><a href="http://www.derivante.com/2009/05/14/php-activerecord-with-php-53/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<h3>Update!</h3>
<p>Find the latest <a href="http://www.derivante.com/2009/05/19/php-activerecord-available-for-beta-testing/">here</a>. </p>
<h2>PHP 5.3 gets ActiveRecord!</h2>
<p><img height="51" width="95" alt="php-med-trans-light" src="http://www.derivante.com/wp-content/uploads/2009/05/php-med-trans-light.gif" title="php-med-trans-light" style="margin: 15px;" class="alignleft size-full wp-image-425"/>A quick search to find an implementation of active record for php on <a title="google" href="http://www.google.com/search?q=php+activerecord" target="_blank">google</a> is discouraging when one considers the state of ActiveRecord for Ruby on Rails. The reader will notice that the top results are from very old posts and the rest of the results preview minimial implementations. Of course, eventually, PHP will see a robust active record similar to RoR. Fortunately, that time is now, thanks to <a href="http://downloads.php.net/johannes/php-5.3.0RC2.tar.gz">PHP 5.3</a> and the beneficial <a href="http://wiki.php.net/doc/scratchpad/upgrade/53">new</a> <a href="http://www.sitepoint.com/article/whats-new-php-5-3/">features</a>: closures, late static binding, and <a href="http://us2.php.net/manual/en/language.namespaces.rationale.php">namespaces</a>.</p>
<p>My friend Kien and I have improved upon an earlier version of an ORM that he had written prior to PHP 5.3. The ActiveRecord we have created is inspired by Ruby on Rails and we have tried to maintain their conventions while deviating mainly because of convenience or necessity. Our main goal for this project has been to allow PHP developers tackle larger projects with greater agility. However, we also hope that use of this resource will push the PHP community further by learning the wonderful benefits of the Ruby on Rails stack. Enough with the rambling, let's get to the interesting piece!</p>
<p><span id="more-391"></span></p>
<h2>Overview</h2>
<p>Allow me to reiterate the fact that we have tried to maintain similarity between our implementation and rails' ActiveRecord to avoid headaches and increase programmer bandwidth. Keeping this similarity in mind, we have tried to re-produce many of the features. Here is a list of those features:</p>
<ul>
<li><a href="#finder_methods">Finder methods</a></li>
<li><a href="#dynamic_methods">Dynamic finder methods</a></li>
<li><a href="#writer_methods">Writer methods</a></li>
<li><a href="#relationships">Relationships</a></li>
<li><a href="#validations">Validations</a></li>
<li><a href="#callbacks">Callbacks</a></li>
<li><a href="#serializations">Serializations</a></li>
<li><a href="#adapters">Support for multiple adapters</a></li>
<li><a href="#misc_options">Miscellaneous options</a></li>
</ul>
<p><br/><br />
There are other features such as named scopes, additional adapters, <strong>transactions</strong> (something we want sooner than later), and a few others we hope to add in the future, but we believe this is a great start. We are hoping to have the code hosted on launchpad or the like within a week or two and a website with documentation. Be sure to check back here shortly for updates!</p>
<h2> Configuration </h2>
<p>Setup is very easy and straight-forward. There are essentially only two configuration points you must concern yourself with:</p>
<ul>
<li>Setting the model auto_load directory.</li>
<li>Configuring your database connections</li>
</ul>
<p>Examples:<br />
<code></p>
<pre class="php">&nbsp;
ActiveRecord\Config::<span style="color: #006600;">initialize</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$cfg</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_model_directory</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/path/to/your/model_directory'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_connections</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'development'</span> =&gt;
       <span style="color: #ff0000;">'mysql://username:password@localhost/database_name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#Alternatively (w/o the 5.3 closure):</span>
<span style="color: #0000ff;">$cfg</span> = ActiveRecord\Config::<span style="color: #006600;">instance</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_model_directory</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/path/to/your/model_directory'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$cfg</span>-&gt;<span style="color: #006600;">set_connections</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'development'</span> =&gt;
    <span style="color: #ff0000;">'mysql://username:password@localhost/database_name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p></code></p>
<p>Once you have configured these two settings you are done. ActiveRecord takes care of the rest for you. It does not require that you map your table schema to yaml/xml files. It will query the database for this information and cache it so that it does not make multiple calls to the database for a single schema.</p>
<h2><a name="finder_methods">Finder methods</a></h2>
<p>ActiveRecord supports a number of methods by which you can find records either by primary key or you can construct your own complex conditions array with other options such as:  order, limit, select, group.<br />
<code></p>
<pre class="php">&nbsp;
<span style="color: #808080; font-style: italic;">#find by primary key</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#same as above but expecting multiple results</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#find the first record with limit</span>
Author::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; 
&nbsp;
<span style="color: #808080; font-style: italic;">#find last record by order and limit</span>
Author::<span style="color: #006600;">last</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; 
&nbsp;
Author::<span style="color: #006600;">all</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; 
&nbsp;
<span style="color: #808080; font-style: italic;">#this may be evil - but you can pass your raw sql to this method</span>
Author::<span style="color: #006600;">find_by_sql</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">## you can also pass many options to finder methods</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; ORDER BY name</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span>,<a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'order'</span> =&gt; <span style="color: #ff0000;">'name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; WHERE author_id IN (1,2,3)</span>
<span style="color: #808080; font-style: italic;">#find all with conditions as array</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'all'</span>,
  <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'conditions'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'author_id IN(?)'</span>,<a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; WHERE author_id = 3</span>
<span style="color: #808080; font-style: italic;">#find with conditions as string</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'first'</span>,<a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'conditions'</span> =&gt; <span style="color: #ff0000;">'author_id=3'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; GROUP BY name</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span>, <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'group'</span> =&gt; <span style="color: #ff0000;">'name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; LIMIT 0,3</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'all'</span>, <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'limit'</span> =&gt; <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; select * from `author` INNER JOIN etc...</span>
Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'all'</span>, <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'joins'</span> =&gt;
  <span style="color: #ff0000;">'INNER JOIN book on (book.author_id = author.id)'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#sql =&gt; SELECT name FROM table</span>
Author::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'select'</span> =&gt; <span style="color: #ff0000;">'name'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#these methods do not return records</span>
<span style="color: #808080; font-style: italic;">#return true/false</span>
Author::<span style="color: #006600;">exists</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#return integer</span>
Author::<a style="text-decoration: none;" href="http://www.php.net/count"><span style="color: #000066;">count</span></a><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'conditions'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'name = ?'</span>, <span style="color: #ff0000;">'John'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;"># access is self-evident</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">title</span>;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">author_id</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#returns an array</span>
<span style="color: #0000ff;">$books</span> = Book::<span style="color: #006600;">all</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$books</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>-&gt;<span style="color: #006600;">title</span>;
&nbsp;</pre>
<p></code></p>
<h2><a name="dynamic_methods">Dynamic finder methods</a></h2>
<p>ActiveRecord within rails makes clever use of finders by allowing you to dynamically create methods based on the attribute names. This means you can easily make a "find_by_attribute_name" query without having to explicitly define it in the class. We also make use of this feature by using a new PHP 5.3 magic method: __callStatic().<br />
<code></p>
<pre class="php">&nbsp;
Author::<span style="color: #006600;">find_by_name</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'George Bush'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #808080; font-style: italic;">#you can make use of and/or</span>
Author::<span style="color: #006600;">find_by_name_or_author_id</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'George Bush'</span>, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>;
Person::<span style="color: #006600;">find_by_first_name_and_last_name</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Obama'</span>, <span style="color: #ff0000;">'Mama'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #808080; font-style: italic;">#also have find_all_by</span>
Author::<span style="color: #006600;">find_all_by_name</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Tito'</span><span style="color: #66cc66;">&#41;</span>;
Author::<span style="color: #006600;">find_all_by_name</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Tito'</span>,<span style="color: #ff0000;">'Bill Clinton'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p></code></p>
<h2><a name="writer_methods">Writer methods</a></h2>
<p>What good is it to have an object that encapsulates a record from the database if you can't do anything with it?<br />
<code></p>
<pre class="php">&nbsp;
<span style="color: #808080; font-style: italic;">#call to SQL insert since it knows that it is a new record</span>
<span style="color: #0000ff;">$book</span> = <span style="color: #000000; font-weight: bold;">new</span> Artist<span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'name'</span> =&gt; <span style="color: #ff0000;">'Tito'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">## updates</span>
<span style="color: #808080; font-style: italic;">#only update 'dirty' attributes meaning the sql would only update</span>
<span style="color: #808080; font-style: italic;">#fields that have been changed</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">title</span> = <span style="color: #ff0000;">'new title!'</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#this will automatically call save</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">update_attributes</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span> =&gt; <span style="color: #ff0000;">'new title!'</span>,
  <span style="color: #ff0000;">'price'</span> =&gt; <span style="color: #cc66cc;">5.00</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#will also make call to save</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">update_attribute</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span>, <span style="color: #ff0000;">'some new title'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$book</span> = <span style="color: #000000; font-weight: bold;">new</span> Book;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">title</span> = <span style="color: #ff0000;">'new title!'</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">author_id</span> = <span style="color: #cc66cc;">5</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">created_at</span> <span style="color: #808080; font-style: italic;"># we also support created_at/updated_at timestamps where applicable</span>
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">id</span>; <span style="color: #808080; font-style: italic;">#id is also set to the auto increment value from the db</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#delete</span>
<span style="color: #0000ff;">$author</span> = Author::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$author</span>-&gt;<span style="color: #006600;">delete</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#you can pass readonly on the find so that you cannot save a model</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'readonly'</span> =&gt; <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">title</span> = <span style="color: #ff0000;">'new'</span>; <span style="color: #808080; font-style: italic;"># or you could set it here by doing $book-&gt;readonly(true);</span>
<span style="color: #808080; font-style: italic;">#this will throw an ActiveRecord\ReadonlyException</span>
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p></code></p>
<h2><a name="relationships">Relationships</a></h2>
<p>Associations are the complex piece of ActiveRecord. They accept many of the same options as with rails.<br />
<code></p>
<pre class="php">&nbsp;
<span style="color: #808080; font-style: italic;">#relationships are declared with a static var</span>
<span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model <span style="color: #66cc66;">&#123;</span>
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$belongs_to</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'publisher'</span><span style="color: #66cc66;">&#41;</span>,
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'author'</span>, <span style="color: #ff0000;">'readonly'</span> =&gt; <span style="color: #000000; font-weight: bold;">true</span>, <span style="color: #ff0000;">'select'</span> =&gt; <span style="color: #ff0000;">'name'</span>, <span style="color: #ff0000;">'conditions'</span> =&gt; <span style="color: #ff0000;">&quot;name != 'jax'&quot;</span><span style="color: #66cc66;">&#41;</span>,
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'another'</span>, <span style="color: #ff0000;">'class_name'</span> =&gt; <span style="color: #ff0000;">'SomeModel'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
  <span style="color: #808080; font-style: italic;">#has_many accepts select/conditions/limit/readonly/group/primary_key</span>
  <span style="color: #808080; font-style: italic;">#has_many also takes a through option which you can use with source</span>
  <span style="color: #808080; font-style: italic;">#to clarify the class</span>
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$has_many</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'revisions'</span><span style="color: #66cc66;">&#41;</span>,
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'editors'</span>, <span style="color: #ff0000;">'through'</span> =&gt; <span style="color: #ff0000;">'revisions'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$has_one</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'something'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#the 0 index declaration array of each association is the &quot;attribute_name&quot;</span>
<span style="color: #808080; font-style: italic;">#which you use to access on the model like so:</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">publisher</span>-&gt;<span style="color: #006600;">name</span>;
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">author</span>-&gt;<span style="color: #006600;">name</span>; <span style="color: #808080; font-style: italic;"># we only have name as an attribute b/c of the select opt</span>
<span style="color: #808080; font-style: italic;">#below will throw a readonlyException due to the option -- see the writer</span>
<span style="color: #808080; font-style: italic;">#methods section</span>
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">author</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#has_many</span>
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">revisions</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>-&gt;<span style="color: #006600;">id</span>;
<span style="color: #808080; font-style: italic;">#has_many through</span>
<a style="text-decoration: none;" href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">editors</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>-&gt;<span style="color: #006600;">name</span>;
&nbsp;</pre>
<p></code></p>
<h2><a name="validations">Validations</a></h2>
<p>This is rather self-explanatory. Before save/update/insert, your validations will be called for each declaration you have made and will save the model if all validations have passed. Otherwise, you will have access to an errors attribute which you can use to get back validation error messages.</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model
<span style="color: #66cc66;">&#123;</span>
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_format_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span>, <span style="color: #ff0000;">'with'</span> =&gt; <span style="color: #ff0000;">'/^[a-zW]*$/'</span>, <span style="color: #ff0000;">'allow_blank'</span> =&gt; <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_exclusion_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span>, <span style="color: #ff0000;">'in'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'blah'</span>, <span style="color: #ff0000;">'alpha'</span>, <span style="color: #ff0000;">'bravo'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_inclusion_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span>, <span style="color: #ff0000;">'within'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'tragedy of dubya'</span>, <span style="color: #ff0000;">'sharks wit laserz'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_length_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span>, <span style="color: #ff0000;">'within'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>, <span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'attribute2'</span>, <span style="color: #ff0000;">'in'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'attribute3'</span>, <span style="color: #ff0000;">'is'</span> =&gt; <span style="color: #cc66cc;">4</span>, <span style="color: #ff0000;">'allow_null'</span> =&gt; <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
  <span style="color: #808080; font-style: italic;"># same as above since it is just an alias</span>
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_size_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_numericality_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$validates_presence_of</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>;
&nbsp;
<span style="color: #0000ff;">$book</span> = <span style="color: #000000; font-weight: bold;">new</span> Book;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">title</span> = <span style="color: #ff0000;">'this is not part of the inclusion'</span>;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>!<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <a style="text-decoration: none;" href="http://www.php.net/print_r"><span style="color: #000066;">print_r</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">errors</span>-&gt;<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'title'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<h2><a name="callbacks">Callbacks</a></h2>
<p>Callbacks allow you to take command of your model before/after certain events during its lifecycle. You can define methods in your model that will occur as callbacks before or after other methods are invoked on the model. Unfortunately, even though PHP 5.3 has closures, you cannot use them in a static var declaration so you must define/use methods.<br />
<code></p>
<pre class="php">&nbsp;
<span style="color: #808080; font-style: italic;">#below are the possible declarations that you can make</span>
<span style="color: #808080; font-style: italic;">#if your callback returns false for a before_* then it will cancel the</span>
<span style="color: #808080; font-style: italic;">#action and the rest of the callbacks</span>
<span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecordModel<span style="color: #66cc66;">&#123;</span>
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_construct</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_save</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'do_something_before_save'</span><span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_save</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_create</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_create</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_update</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_update</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_validation</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_validation</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_validation_on_create</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_validation_on_create</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_validation_on_update</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_validation_on_update</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$before_destroy</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$after_destroy</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">#this will be called directly before save()</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> do_something_before_save<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p></code></p>
<h2><a name="serializations">Serializations</a></h2>
<p><code></p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> upper_title<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <a style="text-decoration: none;" href="http://www.php.net/strtoupper"><span style="color: #000066;">strtoupper</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">title</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#produces: {title: 'sharks wit lazers', author_id: 2}</span>
<span style="color: #0000ff;">$book</span> = Book::<span style="color: #006600;">find</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">to_json</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; 
&nbsp;
<span style="color: #808080; font-style: italic;">#produces: {title: 'sharks wit lazers'}</span>
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">to_json</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'except'</span> =&gt; <span style="color: #ff0000;">'author_id'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#produces:  {upper_title: 'SHARKS WIT LAZERS'}</span>
<span style="color: #808080; font-style: italic;">#make methods an array of methods and it will call them all</span>
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">to_json</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'methods'</span> =&gt; <span style="color: #ff0000;">'upper_title'</span>, <span style="color: #ff0000;">'only'</span> =&gt; <span style="color: #ff0000;">'upper_title'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; 
&nbsp;
<span style="color: #808080; font-style: italic;">#produces {title: 'sharks wit lazers', author_id: 2}</span>
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">to_json</span><span style="color: #66cc66;">&#40;</span><a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'include'</span> =&gt; <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'author'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">#also support xml w/ the same options but need more tests =)</span>
<span style="color: #0000ff;">$book</span>-&gt;<span style="color: #006600;">to_xml</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;</pre>
<p></code></p>
<h2><a name="adapters">Support for multiple adapters</a></h2>
<p>Currently, there exists support only for <strong>MySQL</strong> (also through mysqli) and <strong>sqlite3</strong>. Right now there are only two contributors to the code base; however, we hope to attract more coders to the project that can help support additional adapters such as postgres and oracle. The connection/adapter piece of the code has been sufficiently abstracted so that it should not be difficult to create more adapters when the time comes.</p>
<h2><a name="misc_options">Miscellaneous Options</a></h2>
<p>When declaring a model you can also specify the primary_key and table_name. Protected/accessible declarations are available so that you can avoid mass assignment problems. Attributes can be aliased so that you may access them via different names.<br />
<code></p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Book <span style="color: #000000; font-weight: bold;">extends</span> ActiveRecord\Model<span style="color: #66cc66;">&#123;</span>
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$primary_key</span> = <span style="color: #ff0000;">'book_id'</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$table_name</span> = <span style="color: #ff0000;">'book_table'</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$attr_accessible</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'author_id'</span><span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$attr_protected</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'book_id'</span><span style="color: #66cc66;">&#41;</span>;
  <a style="text-decoration: none;" href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #0000ff;">$alias_attribute</span> = <a style="text-decoration: none;" href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'new_alias'</span> =&gt; <span style="color: #ff0000;">'actual_attribute'</span>,
    <span style="color: #ff0000;">'new_alias_two'</span> =&gt; <span style="color: #ff0000;">'other_actual_attribute'</span>
  <span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p></code></p>
<h2>The Future</h2>
<p>As I stated previously, very shortly the code will be available on launchpad. We are also in the works of putting up a website to host tutorials and documentation for the code. I will make additional posts once those milestones have been reached. Thanks for reading.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/05/14/php-activerecord-with-php-53/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>SOLR Performance Benchmarks – Single vs. Multi-core Index Shards</title>
		<link>http://www.derivante.com/2009/05/05/solr-performance-benchmarks-single-vs-multi-core-index-shards/</link>
		<comments>http://www.derivante.com/2009/05/05/solr-performance-benchmarks-single-vs-multi-core-index-shards/#comments</comments>
		<pubDate>Tue, 05 May 2009 22:23:13 +0000</pubDate>
		<dc:creator>Justin Leider</dc:creator>
				<category><![CDATA[SOLR]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[Shards]]></category>
		<category><![CDATA[Throughput]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=350</guid>
		<description><![CDATA[Single vs. multi-core sharded index. Which one is the right one? There is not a whole lot of information out there, especially when it comes to hard numbers and comparisons. There are a couple reasons for this. The first one (&#8230;)</p><p><a href="http://www.derivante.com/2009/05/05/solr-performance-benchmarks-single-vs-multi-core-index-shards/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-415" title="solr_fc" src="http://www.derivante.com/wp-content/uploads/2009/05/solr_fc.jpg" alt="solr_fc" width="170" height="94" />Single vs. <a title="SOLR multi-core indexing" href="http://wiki.apache.org/solr/CoreAdmin" target="_blank">multi-core sharded index</a>. Which one is the right one? There is not a whole lot of information out there, especially when it comes to hard numbers and comparisons. There are a couple reasons for this. The first one that comes to mind is the multi-core functionality offered by <a title="SOLR Search Engine" href="http://lucene.apache.org/solr/" target="_blank">Apache SOLR</a> is very nascent. It was recently introduced with the latest SOLR v1.3 and hasn't had much time to be adopted by the SOLR community. Second, the results are dependent on your schema, index size, query types and user load. These factors can account for varying performance results. As evidenced by the following benchmarks, a multi-core SOLR index has the potential to speed up the performance of your application or cut throughput and scalability by approximately the inverse number of cores.</p>
<p style="margin-bottom: 0in; padding-left: 30px;">i.e. For n cores the maximum throughput is roughly 1/n vs. a single index.</p>
<p style="margin-bottom: 0in;">With multi-core sharded indexes the underlying assumption is that search performance improves by splitting your index into smaller chunks. These smaller shards are then faster and more efficient to search and index. However, you never get anything for free, the performance increase comes at a cost of higher CPU utilization. By breaking the index into multiple smaller pieces it makes searching and indexing on that smaller subset of the index faster, but you'll need to search each core individually for every query. Where as a single index runs one slightly slower query, a multi-core sharded query runs n queries in parallel and then combines the results.</p>
<p><span id="more-350"></span></p>
<p style="margin-bottom: 0in;">There is one problem which still needs to be worked out with the multi-core sharded index. There is no distributed IDF (inverse document frequency). This is to say, if your documents are not spread evenly across all shards then you risk a result set that is improperly ordered based on your sorts, query boosts, etc. This happens with a distributed multi-core index because the scoring of the documents takes place within each individual  core before the results are combined and the query returned.</p>
<p style="margin-bottom: 0in;">Ideally, a multi-core index is great if you need to increase the performance of your queries and can afford to sacrifice some scalability and throughput to see it through.</p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;">Below are some charts of benchmarks that I have compiled on the CitySquares SOLR index. The specifications of the machine and indexes are as follows:</p>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>Testing machine - Dell r900:</strong></p>
<ul>
<li>4x Quad Core Intel(R) Xeon(R) CPU 		E7340 @ 2.40GHz (16 physical cores)</li>
<li>24GB RAM</li>
<li>3x 15k RPM drives in RAID 0</li>
<li>Gig-Ethernet on a local LAN</li>
</ul>
<p style="margin-bottom: 0in;"><strong>Index Stats:</strong></p>
<ul>
<li>14.5 Million Documents</li>
<li>13 GB total size</li>
<li> 56 fields (indexed and/or stored 	w/ various amounts of processing)</li>
<li>Fully optimized index</li>
</ul>
<p style="margin-bottom: 0in;"><strong>Benchmarks:</strong></p>
<ul>
<li>Used Apache Bench for testing purposes from another machine on the same LAN over Gig-E.</li>
</ul>
<pre class="bash">&nbsp;
<span style="color: #808080; font-style: italic;">#!/bin/bash</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&quot;</span> &gt; solr_results.log
<span style="color: #000000; font-weight: bold;">for</span> C <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">2</span> <span style="color: #000000;">4</span> <span style="color: #000000;">8</span> <span style="color: #000000;">16</span> <span style="color: #000000;">32</span> <span style="color: #000000;">64</span> <span style="color: #000000;">128</span> <span style="color: #000000;">256</span> <span style="color: #000000;">512</span>
<span style="color: #000000; font-weight: bold;">do</span>
<span style="color: #007800;">N=</span>$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">$C</span>*<span style="color: #000000;">1000</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;ab -n$N -c$C&quot;</span> &gt;&gt; solr_results.log
ab -n<span style="color: #007800;">$N</span> -c<span style="color: #007800;">$C</span> <span style="color: #ff0000;">'http://solr:8080/solr/select?q=&lt;ID&gt;&amp;qf=&lt;FIELD&gt;&amp;fq=&lt;FIELD&gt;:&lt;ID&gt;&amp;start=0&amp;rows=20'</span> &gt;&gt; solr_results.log
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;</pre>
<p style="margin-bottom: 0in;">
<p style="margin-bottom: 0in;"><strong>For the trends in red the lower the number the better.<br />
For the trends in blue the higher the number the better.</strong></p>
<p style="margin-bottom: 0in;">
<div class="mceTemp">
<dl id="attachment_356" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Single index with no caching enabled <img class="size-full wp-image-356" title="single-index-no-cache" src="http://www.derivante.com/wp-content/uploads/2009/04/single-index-no-cache.jpg" alt="Single index with no caching enabled" width="500" height="400" /></dt>
</dl>
</div>
<div class="mceTemp">
<dl id="attachment_355" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Single index with filterCache enabled<img class="size-full wp-image-355" title="single-index-cache" src="http://www.derivante.com/wp-content/uploads/2009/04/single-index-cache.jpg" alt="Single index with filterCache enabled" width="500" height="400" /></dt>
</dl>
</div>
<p>We can see here in the above graph that there were no results from the 512 concurrency test. This is because there was a deadlock in the Apache Tomcat server. The max number of connections was set to 512 with an overflow of 100.  This is the cause of all the cases where there are no results for the 512 test case. Ironically the Single core without the cache managed to finish but the test with fieldCache on failed.</p>
<div class="mceTemp">
<dl id="attachment_353" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Multicore Index (2 Cores) with no caching enabled<img class="size-full wp-image-353" title="multicore-no-cache" src="http://www.derivante.com/wp-content/uploads/2009/04/multicore-no-cache.jpg" alt="Multicore Index (2 Cores) with no caching enabled" width="500" height="400" /></dt>
</dl>
</div>
<div class="mceTemp">
<dl id="attachment_352" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Multicore Index (2 Cores) with filterCaching enabled<img class="size-full wp-image-352" title="multicore-cache" src="http://www.derivante.com/wp-content/uploads/2009/04/multicore-cache.jpg" alt="Multicore Index (2 Cores) with filterCaching enabled" width="500" height="400" /></dt>
</dl>
</div>
<p><strong>The higher the better in the following chart.</strong></p>
<div class="mceTemp">
<dl id="attachment_354" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Requests per second across all benchmarks<img class="size-full wp-image-354" title="requests-per-second" src="http://www.derivante.com/wp-content/uploads/2009/04/requests-per-second.jpg" alt="Requests per second across all benchmarks" width="500" height="400" /></dt>
</dl>
</div>
<p><strong>The lower the better in the following charts.</strong></p>
<div class="mceTemp">
<dl id="attachment_357" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Time per request across all benchmarks<img class="size-full wp-image-357" title="time-per-request" src="http://www.derivante.com/wp-content/uploads/2009/04/time-per-request.jpg" alt="Time per request across all benchmarks" width="500" height="400" /></dt>
</dl>
</div>
<p>The above graph shows the only test to finish successfully with 512 concurrent connections was the single index with caching disabled.</p>
<div class="mceTemp">
<dl id="attachment_362" class="wp-caption alignnone" style="width: 510px;">
<dt class="wp-caption-dt">Time per request across all benchmarks (truncated view)<img class="size-full wp-image-362" title="time-per-request-zoom" src="http://www.derivante.com/wp-content/uploads/2009/04/time-per-request-zoom.jpg" alt="Time per request across all benchmarks (truncated view)" width="500" height="400" /></dt>
</dl>
</div>
<p>This graph is the same as the one before without the last two concurrency levels so you can see whats going on at the beginning of the benchmark. Its still hard to see but the multi-core sharded indexes are a bit lower that the single indexes. Its clear however at the higher concurrencies that the single indexes beat the multi-core ones hands down.</p>
<p>Ive attached a <a title="SOLR Benchmarks" href="http://www.derivante.com/wp-content/uploads/2009/04/solr-blog-benchmarks.xls" target="_blank">spreadsheet</a> with actual numbers from the benchmarks since some of the charts are hard to read.</p>
<p>So there it is, take it as you will. There are definitely benefits to moving from a single index to a distributed multi-core sharded index. However, whether it works for your dataset and application is up in the air. After these benchmarks we decided that the multi-core index that had served us well on <a title="Limitations of scaling with EC2" href="http://www.derivante.com/2008/10/08/the-limitations-of-scaling-with-ec2/" target="_blank">Amazon's EC2</a> no longer worked well for us on our new managed hosting. We are currently running a single index at <a title="CitySquares Online -- Hyper Local Neighborhood Search" href="http://citysquares.com" target="_blank">CitySquares</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/05/05/solr-performance-benchmarks-single-vs-multi-core-index-shards/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>100x Increase in SOLR Performance and Throughput</title>
		<link>http://www.derivante.com/2009/04/27/100x-increase-in-solr-performance-and-throughput/</link>
		<comments>http://www.derivante.com/2009/04/27/100x-increase-in-solr-performance-and-throughput/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 20:28:27 +0000</pubDate>
		<dc:creator>Justin Leider</dc:creator>
				<category><![CDATA[SOLR]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[scalability]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=341</guid>
		<description><![CDATA[Is your SOLR installation running slower than you think it should? Performance, throughput and scalability not what you are expecting or hoping? Do you constantly see that others have much higher SOLR query performance and scalability than you do? All (&#8230;)</p><p><a href="http://www.derivante.com/2009/04/27/100x-increase-in-solr-performance-and-throughput/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" style="margin: 5px;" title="SOLR" src="http://www.derivante.com/wp-content/uploads/2009/05/solr_fc.jpg" alt="" width="170" height="94" />Is your SOLR installation running slower than you think it should? Performance, throughput and scalability not what you are expecting or hoping? Do you constantly see that others have much higher SOLR query performance and scalability than you do? All it might take to fix your woes is a simple schema or query change.</p>
<p>The following scenario I am about to describe is proof positive that you should always take the time to understand the underlying functionality of whatever operating system, programming language or application you are using. Let my oversight and 'quick fix solution' be a lesson to you, it is almost always worth the upfront cost of doing something right the first time so you don't have to keep revisiting the same issue.<br><br />
<span id="more-341"></span><br />
Before I delve into the nuances of SOLR let me first give you some background on what took place over the last half year at CitySquares. Back in the fall of last year the CitySquares website began experiencing an exponential growth in traffic. This growth was due to an expansion of its IYP (Internet Yellow Page) services into the New England and Metro New York areas. Prior to and during the beginning of the first wave of traffic growth, every business listing was powered by very large MySQL queries including a couple joins. The queries themselves weren't all that complex but they were big and unwieldy with joins on very large tables and lots of columns in the result sets. In some of the larger cities covered at the time (Manhattan, Bronx, Queens, Boston, etc) there were up to 100,000 rows of data that needed to be sorted before returning a rather small subset (20-40 rows) for each business listing page load. While this wasn't a big deal when CitySquares was still a niche Boston centric destination, it quickly became a huge burden on the MySQL servers. Some of these queries were so big the servers would run out of memory trying to crunch through a 3GB temp table and start thrashing the disks to server a request for Manhattan. We needed a better solution and quick.</p>
<p>Luckily for us we had already implemented a SOLR search engine with all the necessary data indexed from our database initially with the sole intent that search result sets shouldn't have to query the database. This worked to our advantage since it was very easy for us to modify the code base to query SOLR instead of MySQL. Both result sets were formatted as an object with the same field names and all. It was a perfect drop in replacement.</p>
<p>The SOLR solution we implemented utilized SOLR's wild card q.alt=*:* field to select all documents while applying filter query (fq) on that set to get all documents related to our filter. It was a huge win for us at the time. Not only were the queries faster than the MySQL ones, but the SOLR servers could handle more of these queries without even coming close to exhausting the server's resources. This quick and dirty solution was satisfactory for the next few months until CitySquares' next round of expansion began, where again, the queries became a burden. The second time around we didn't have another seemingly quick fix. I spent a couple days trying to figure out a better way to implement the q.alt=*:* field but to no avail I gave up and moved onto other performance optimizations.</p>
<p>Unfortunately, I didn't take the time to understand the code behind the query and I didn't understand exactly how SOLR was implementing the query in its back end process. Since I didn't understand the basis of the problem I couldn't possibly know the query could be easily re-factored. After a few weeks of high loads, 20+ on our 8 core servers, I struck up a conversation with Michael, the developer who wrote the query. We discussed how the query worked and what it needed to do and after five minutes we had discovered a much better way to structure the query. It took me only about a minute or two to re-factor the original query to produce the exact same result set. This new query was incredibly fast! I benchmarked it to be about 100x faster than the previous query and on top of that it was a simple drop in replacement!</p>
<p>From what I've deduced the original query passed a blank query string with a filter query to SOLR which in turn defaulted to the q.alt catch all first and then applied the filter on the catch all query. This is exactly the opposite of what we were expecting SOLR to do. We believed that the filter was applied first and then the q.alt was applied. However, that was not the case. while this misunderstanding wasn't ideal it wasn't too slow either with only 1.4 million documents to parse over. However once CitySquares hit the 14.5 million mark this query became unmanageable. Basically SOLR parsed over every single document in the index before applying the query filter we were using. To rectify this and regain performance and through put on our servers I simply moved the filter query statement to the query statement and specified the query field to be the same as the original filter field.</p>
<p>i.e.</p>
<p>Original query passed a blank query string with a filter query:</p>
<ul>
<li>select?q=+&amp;fq=&lt;FIELD&gt;:&lt;ID&gt;</li>
</ul>
<p>The updated query now passes the id as the query string and specifies the former filter field:</p>
<ul>
<li>select?q=&lt;ID&gt;&amp;qf=&lt;FIELD&gt;</li>
</ul>
<p>Instead of taking advantages of SOLR's and every other search engines strength of O(1) search time we were at the mercy of its worst case scenario O(n) scan time. This simple misunderstanding of how SOLR processes queries in the back end caused massive performance and throughput bottlenecks. These bottlenecks affected our short and long term infrastructure plans, and was the root cause of many performance headaches for our users, customers and IT department.</p>
<p>If this isn't proof positive that you should always take the time to understand the underlying functionality of whatever operating system, programming language or application you are using I don't know what is.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/04/27/100x-increase-in-solr-performance-and-throughput/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>PHP/KML Polyline Simplification with Douglas-Peucker</title>
		<link>http://www.derivante.com/2009/04/20/phpkml-polyline-simplification-with-douglas-peucker/</link>
		<comments>http://www.derivante.com/2009/04/20/phpkml-polyline-simplification-with-douglas-peucker/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 02:41:16 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Technology]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=331</guid>
		<description><![CDATA[Quality GIS data sometimes comes with a lot more precision than what is usable for Google Maps (or other mapping software). The problem lies in the number of points representing a polygon that you want to overlay. A county representation (&#8230;)</p><p><a href="http://www.derivante.com/2009/04/20/phpkml-polyline-simplification-with-douglas-peucker/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-425" style="margin: 15px;" title="php-med-trans-light" src="http://www.derivante.com/wp-content/uploads/2009/05/php-med-trans-light.gif" alt="php-med-trans-light" width="95" height="51" />Quality GIS data sometimes comes with a lot more precision than what is usable for Google Maps (or other mapping software). The problem lies in the number of points representing a polygon that you want to overlay. A county representation for a state might include 100,000 points that is not usable without some form of reduction. Luckily there is an algorithm that solves that problem, Douglas-Peucker.</p>
<p>The algorithm simplifies a polyline by removing vertices that do not contribute (sufficiently) to the overall shape. It is a recursive process which finds the most important vertices for every given reduction. First, the most basic reduction is assumed. A single segment connecting the beginning and end of the original polyline. This is when the recursion starts, the most significant vertex (the most distant) for this segment is found and, when the distance from this vertex to the segment exceeds the reduction tolerance, the segment is split into two sub-segments, each inheriting a subset of the original vertex list. Each segment continues to subdivide until none of the vertices in the local list are further away than the tolerance value.</p>
<p>There is a PHP class that does just this: <a href="http://www.fonant.com/demos/douglas_peucker/algorithm">Douglas-Peucker Polyline Simplification in PHP</a> by <a href="http://www.fonant.com/">Anthony Cartmell</a>. Based on the original quality of the data and tolerance level, I was able to achieve a 90-93% reduction in size. This reduction allows me to represent significantly more data at a reasonable performance level to clients. Keep in mind, that this reduction is removing data out of the coordinate array so the quality of your representation will go down with the tolerance and reduction being applied. I highly suggest that you play around with the tolerance until you find a good balance between data size and image quality.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/04/20/phpkml-polyline-simplification-with-douglas-peucker/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP GIS Functions</title>
		<link>http://www.derivante.com/2009/04/14/php-gis-functions/</link>
		<comments>http://www.derivante.com/2009/04/14/php-gis-functions/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 17:35:53 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=313</guid>
		<description><![CDATA[I have been working a lot of with PHP and GIS consulting for CitySquares and the History Engine. I found searching for everything I needed to do basic processing &#38; Google Integration tedious and painful. So here is a collection (&#8230;)</p><p><a href="http://www.derivante.com/2009/04/14/php-gis-functions/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-425" style="margin: 15px;" title="php-med-trans-light" src="http://www.derivante.com/wp-content/uploads/2009/05/php-med-trans-light.gif" alt="php-med-trans-light" width="95" height="51" />I have been working a lot of with PHP and GIS consulting for <a href="http://citysquares.com">CitySquares </a>and the <a href="http://historyengine.richmond.edu/">History Engine</a>.  I found searching for everything I needed to do basic processing &amp; Google Integration tedious and painful.  So here is a collection of common functions that helped me get through the <em>massaging</em> of the data and ready for integration.</p>
<ul style="padding-left: 20px;padding-bottom: 10px;"> <strong><a href="http://www.derivante.com/files/phpgis.txt">pnPoly</a></strong> - Used to determine if a coordinate falls inside a polygon.<br />
<strong><a href="http://www.derivante.com/files/phpgis.txt">Centroid </a></strong>- Find the center of a polygon..<br />
<strong><a href="http://www.derivante.com/files/phpgis.txt">Area</a></strong> - Calculate the area of a polygon.<br />
<strong><a href="http://www.derivante.com/files/geocoder.txt">googleGeoCoder </a></strong> - Extracts GIS information from Google Maps from an address.<br />
<strong><a href="http://www.derivante.com/files/polyline.txt">PolylineEncoder</a></strong> - Takes a set of coordinates and encodes it for Google Maps.</ul>
<p>If you ran into the problem I did, which is that a lot of the data is coming in the form of shp/dbf files and needs to be parsed out to something friendlier either KML or CSV, there are a couple of solutions for that.  You can parse out the data with <a href="http://www.obviously.com/gis/shp2text/">shp2text</a> if your source coordinate format is already in lat/lng or if you have different coordinate system and use ArcGIS, you can try the plugin <a href="http://arcscripts.esri.com/details.asp?dbid=14273">Export to KML 2.5.3</a> to help with the exporting of data with the ESRI suite of products.</p>
<p>Once your data is in SQL, the following query is an example of distance sorting with SQL. You can grab a copy of the zip_codes database <a href="http://www.derivante.com/files/zip_codes.sql.gz">here</a> and play around with it.</p>
<pre style="padding-left: 20px;padding-bottom: 10px;" lang="sql">SELECT *,
sqrt((69.1 * ("37.6" - latitude)) * (69.1 * ("37.6" - latitude)) +
(53.0 * ("-77.6" - longitude)) * (53.0 * ("-77.6" - longitude)))
AS distance
FROM `zip_codes`
HAVING distance &lt; 10
ORDER BY distance ASC</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/04/14/php-gis-functions/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Bayesian filter training with N-gram</title>
		<link>http://www.derivante.com/2009/03/31/bayesian-filter-training-with-n-gram/</link>
		<comments>http://www.derivante.com/2009/03/31/bayesian-filter-training-with-n-gram/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 04:09:19 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=274</guid>
		<description><![CDATA[Bayesian filtering is based on the principle that most events are dependent and that the probability of an event occurring in the future can be inferred from the previous occurrences of that event (link). A probability value is then assigned (&#8230;)</p><p><a href="http://www.derivante.com/2009/03/31/bayesian-filter-training-with-n-gram/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Bayesian filtering is based on the principle that most events are dependent and that the probability of an event occurring in the future can be inferred from the previous occurrences of that event (<a href="http://support.gfi.com/manuals/en/me12/me12manual.1.13.html">link</a>).  A probability value is then assigned to each word or token; the probability is based on calculations that take into account how often that word occurs in one category or another.  The most common application of the filter is for identifying words that appear in spam versus legitimate emails. A word by itself is often times useless without the context  it was used in.</p>
<p>There is a whole suite of tools that are able to break down content to help improve the filter by supplementing it not only with a database of words to categories, but also sets of <a href="http://en.wikipedia.org/wiki/N-gram">N-gram</a> derived from the text.   There are several scripts out there that will help with this extraction and it offers a few more layers of depth for Bayesian filtering.  One such tool is, <a href="http://ngram.sourceforge.net/">Ngram Statistics Package (NSP)</a> which is easy to install and run.</p>
<p><span id="more-274"></span><br />
I ran a very basic test against an older <a href="http://www.derivante.com/2009/01/26/there-and-back-again-an-ec2-mysql-cluster/">post</a> to see how it does with bigram extraction.</p>
<p># perl bin/count.pl --ngram 2 test.cnt test.txt<br />
# perl statistic.pl --ngram 2 dice test.res test.cnt</p>
<p>Sample bigrams found:</p>
<p>cloud computing, master slave, groups online, Back Again, made absolutely, very costly, extensive development, hefty bill, start ups, distribution awareness</p>
<p>Rather than running a probability that the set of words above would fit into one category in this case, "Technology" we can now compound the score with the probability that those terms fall into the category as well.  For another layer of scoring, trigrams can be extracted, 4-grams, etc.  In the financial sector the terminology is thick and analysis will be almost impossible without N-gram extraction.  "Filed for bankruptcy" and "avoided bankruptcy" could not be further apart.  With traditional filtering, the word "bankruptcy" would be meaningless because it really is not an indicator as to the probability that the article is favorable or not because there is no context.  In this case by extracting the phrases the filter can understand and score appropriate the difference between the two terms.</p>
<p>Paul Graham has been working on <a href="http://www.bgl.nu/bogofilter/graham.html">improving </a>the Bayesian filter to deal with spam by splitting the data into categories.  Text is classified not only as legitimate or spam based on the context of the message, but the likely hood of tokens appearing in various parts of the message.  N-gram filtering in this case wouldn't work as well for spam as the amount of grammar mistakes, misspellings, and word ordering would make any benefit worthless.   Spammers are adjusting their content to beat such filters all the time.  When the source data is reliable, the N-gram addition to the  filter will boost categorization accuracy.</p>
<p>Integration to traditional Bayesian filtering is very easy.  <a href="http://googleresearch.blogspot.com/2006/08/all-our-n-gram-are-belong-to-you.html">Google</a> has been using text processing for a while now.  This is a huge area of study in linguistics, language processing and machine learning.  With so much data out there and more being collected on a daily basis, deriving context from text will allow for applications to behave smarter.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/03/31/bayesian-filter-training-with-n-gram/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SEO: Taking control of search</title>
		<link>http://www.derivante.com/2009/03/30/seo-taking-control-of-search/</link>
		<comments>http://www.derivante.com/2009/03/30/seo-taking-control-of-search/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 20:56:05 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=265</guid>
		<description><![CDATA[In my experience the majority of web agencies and developers still do not take search seriously enough. Most businesses have very simple requests, "How do I show up for keyword for people in the area", "How do I show up (&#8230;)</p><p><a href="http://www.derivante.com/2009/03/30/seo-taking-control-of-search/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>In my experience the majority of web agencies and developers still do not take search seriously enough.  Most businesses have very simple requests, "How do I show up for <em>keyword </em>for people in the area", "How do I show up higher than my competitor on searches", and "How do people find my site".  The web is an economy and driving consumers to business on the internet is a highly desired skill set.  Consistently controlling the results of Google will be impossible and there is always room for improvement for every site.</p>
<p>Every developer will grow their own set of tools, but the core components are available for free.  Google offers <a href="https://www.google.com/analytics/">analytics</a> to take control of your traffic performance, sources, and patterns.  There is also <a href="https://www.google.com/analytics/">Adwords Keyword Tool</a>, which will help you target search phrases, volume, and competition.   Based on these factors and a list of similar keywords you will be able to identify good opportunities to compete for relevant traffic.  There is also the <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;answer=35769">Webmaster guidelines</a> published by Google that will give you a general best practice for search engines.</p>
<p>This process requires a lot of patience.  It takes time for changes to take shape and results are delivered.  When making changes to any site or even designing a new site with SEO built in, user traffic is not going to happen right away.  Seeing the results come in will trigger an OCD to check Analytics and forever make improvements and indentify new markets and opportunities.   The vast majority of web sites are there for user consumption.  SEO became big business when a lot of people all at once figured out that users translated to consumers.</p>
<p>Google is the search leader, therefore they offer the highest return.  They control the flow of traffic on the internet.  Luckily, they also published a <a href="http://www.google.com/webmasters/docs/search-engine-optimization-starter-guide.pdf">search engine optimization starter guide</a> in pdf format! This is the 101 of SEO and it will be pointless to try to chase down every obscure reference and tip on the countless SEO sites out there when the components to their content analysis is available all in one place.  The document is a general overview but offers some very important best practice rules that are easy to implement:</p>
<p><strong>Title Tags</strong></p>
<p>- Choose a title that effectively communicates the topic of the page's content.<br />
- Create unique title tags for each page<br />
- Use brief, but descriptive titles (limit of 66 characters or 12 keywords)</p>
<p><strong>Description Tags</strong></p>
<p>- Accurately summarize the page's content<br />
- Use unique descriptions for each page<br />
- Avoid filling the description with only keywords<br />
- Avoid copy and pasting the entire content of the document into the description meta tag</p>
<p><strong>URL structure</strong></p>
<p>- Use words in URLs<br />
- Create a simple directory structure<br />
- Provide one version of a URL to reach a document<br />
- Many users expect lower-case URLs and remember them better)</p>
<p><strong>Site Navigation</strong></p>
<p>- Create a naturally flowing hierarchy<br />
- Use mostly text for navigation<br />
- Use "breadcrumb" navigation<br />
- Put an HTML sitemap page on your site, and use an XML Sitemap file<br />
- Consider what happens when a user removes part of your URL<br />
- Have a useful 404 page</p>
<p><strong>Anchor Text (Links)</strong></p>
<p>- Choose descriptive text<br />
- Write concise text<br />
- Format links so they're easy to spot</p>
<p><strong>Heading Text</strong></p>
<p>- There are six sizes of heading tags, beginning with &lt;h1&gt;, the most important, and ending with &lt;h6&gt;, the  least important.<br />
- Imagine you're writing an outline<br />
- Use headings sparingly across the page<br />
- Avoid using heading tags only for styling text and not presenting structure<br />
- Avoid excessively using heading tags throughout the page</p>
<p><strong>Other Confirmed Ranking Factors</strong></p>
<p>- Keyword in URL<br />
- Keyword in Domain name<br />
- Freshness of Pages<br />
- Freshness - Amount of Content Change<br />
- Freshness of Links<br />
- Site Age<br />
- Anchor text of inbound link<br />
- <a href="ftp://ftp.cs.toronto.edu/pub/reports/csri/405/hilltop.html">Hilltop Algorithm</a><br />
- Domain Registration Time</p>
<p>There is a lot of helpful content in the document but it does not go deep into the inner mechanics like other sites attempt to do.   There are several sites out there that try to go beyond what has been published and into the details for generating traffic, you would just need to google "<a href="http://www.google.com/search?q=google+seo+rules">Google Ranking Factors</a>".  A lot of information came from when google released US Patent Application <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO2&amp;Sect2=HITOFF&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsearch-bool.html&amp;r=1&amp;f=G&amp;l=50&amp;co1=AND&amp;d=PG01&amp;s1=20050071741&amp;OS=20050071741&amp;RS=20050071741">#20050071741</a>.</p>
<p>Use the above as a baseline of the steps to get your site more traffic. This is a topic that is constantly being updated as search improves and requires a lot of time and research to do efficiently.  Overhauling existing projects to meet the standards of today's crawlers is tedious, boring, and offers no immediate results.  It has been something I avoided in the past, but for a web site to stay competitive and more importantly, be seen it has to be found.  I find having some good rules in place for how to deal with SEO makes new projects going forward much easier to deal with.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/03/30/seo-taking-control-of-search/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bayesian Filtering &amp; Financial Applications</title>
		<link>http://www.derivante.com/2009/03/27/bayesian-filtering-financial-applications/</link>
		<comments>http://www.derivante.com/2009/03/27/bayesian-filtering-financial-applications/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 17:08:17 +0000</pubDate>
		<dc:creator>Clay vanSchalkwijk</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bayesian]]></category>
		<category><![CDATA[content analysis]]></category>
		<category><![CDATA[Machine Learning]]></category>

		<guid isPermaLink="false">http://www.derivante.com/?p=257</guid>
		<description><![CDATA[A friend of mine and I recently started a new project. After kicking around several ideas we finally reached a consensus on applying software prediction to financial data. This has been pursued pretty heavily but from a home brew stand (&#8230;)</p><p><a href="http://www.derivante.com/2009/03/27/bayesian-filtering-financial-applications/">Read the rest of this entry &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>A friend of mine and I recently started a new project.  After kicking around several ideas we finally reached a consensus on applying software prediction to financial data.  This has been pursued pretty heavily but from a home brew stand point, we wanted to make software that could compete by mashing up existing data and technology available on the internet to make competitive and functioning software.</p>
<p>We intend on predicting the movement of stocks based on real time content analysis.  This requires a good deal of machine learning and historical data, but even good content analysis is not enough.  Using Bayesian Filtering with noise word reduction we plan on processing historical data and assigning the content to one of three categories: moveup, movedown, nomove.  In order to train the filters, past press releases will be inserted into the filter mashed up with the stock data to track how the markets reacted to the context of the content.  Over time, the software will be able to recognize keywords that trigger positive versus negative emotion in the market that would drive the price one way or the other.  A score can be applied much like spam scores are applied and this number can be used as part of a greater overall algorithm to determine an action.</p>
<p>Just to bring a few readers up to speed on exactly how this will be applied, take the following formula:</p>
<p><img class="aligncenter size-full wp-image-263" src="http://www.derivante.com/wp-content/uploads/2009/03/b307149835ea31ced4ae23af2ab89b05.png" alt="" width="437" height="46" /></p>
<p>Rather than training it to recognize the probability of spam we train it to recognize the probability that the word will trigger positive stock movement:</p>
<ul>
<li><span class="texhtml"><em>p</em></span> is the probability that the content will result in positive movement.</li>
<li><span class="texhtml"><em>p</em>1</span> is the probability <span class="texhtml"><em>p</em>(<em>S</em> | <em>W</em>1)</span> that it is positive knowing it contains a first word (for example "capital");</li>
<li><span class="texhtml"><em>p</em>2</span> is the probability <span class="texhtml"><em>p</em>(<em>S</em> | <em>W</em>2)</span> that it is positive knowing it contains a second word (for example "boosted");</li>
<li><em>etc...</em></li>
</ul>
<p>The entire body of the content will be processed against a known database of words and the market reaction to the presence of those words.  The basic Bayesian filtering will need to be extended to deal with phrase recognition but overall a solid proven technology for machine learning to build from.</p>
<p>This information by itself, is nothing revolutionary but with strong pattern analysis like candlestick pattern recognition and other market indicators it can be used to create an accurate trading platform for marginal gains which over time can offer pretty high returns.  There is certainly a lot of potential for this if it works, but it heavily depends on working accurately and there will be a lot of trial and error in the process.</p>
<p>For more reading on the concepts and components behind this idea, check out:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Naive_Bayes_classifier">Naive Bayes Classifier</a></li>
<li><a href="http://www.leavittbrothers.com/education/candlestick_patterns/">Candlestick Patterns</a></li>
<li><a href="http://en.wikipedia.org/wiki/Candlestick_chart">Candlestick Charting</a></li>
<li><a href="http://www.paulgraham.com/better.html">Better Bayesian Filtering</a></li>
<li><a href="http://www.tdameritrade.com/tradingtools/partnertools/api_dev.html">TD Ameritrade API</a></li>
</ul>
<p>The nice part is all the historical data is out there around the internet which makes back-testing and scoring very easy to do and there will need to be a lot of testing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2009/03/27/bayesian-filtering-financial-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
