<?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 &#187; PHP</title>
	<atom:link href="http://www.derivante.com/tag/php/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.0</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. Every caching class I seemed to come by was written specifically for a single back [...]]]></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>3</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 unique. Getting started and putting a solid foundation is the first step and of course, [...]]]></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, site2, etc) are subject to their own individual quotas.   There is no per user account [...]]]></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>Part 2: An Architecture Overview &#8212; Apache, MySQL, Memcached, SQLite</title>
		<link>http://www.derivante.com/2008/07/24/an-architecture-overview-apache-mysql-memcached-sqlite/</link>
		<comments>http://www.derivante.com/2008/07/24/an-architecture-overview-apache-mysql-memcached-sqlite/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 19:56:41 +0000</pubDate>
		<dc:creator>Justin Leider</dc:creator>
				<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[citysquares]]></category>
		<category><![CDATA[horizontal architecture]]></category>
		<category><![CDATA[horizontal database]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[SOLR]]></category>
		<category><![CDATA[sqlite]]></category>
		<category><![CDATA[xcache]]></category>

		<guid isPermaLink="false">http://justinleider.wordpress.com/?p=11</guid>
		<description><![CDATA[In my last post I mentioned the numerous technologies which were on tap for the upcoming version of CitySquares. This installment will continue to define an overview of the underlying architecture and begin to dig a little deeper into the actual implementation of the technologies. The idea and focus of this new architecture is aimed [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } --></p>
<p style="margin-bottom:0;">In my last post I mentioned the numerous technologies which were on tap for the upcoming version of <a title="CitySquares Online -- Hyper Local Neighborhood Search" href="http://citysquares.com" target="_blank">CitySquares</a>. This installment will continue to define an overview of the underlying architecture and begin to dig a little deeper into the actual implementation of the technologies. The idea and focus of this new architecture is aimed at creating a much more stable and scalable platform for us to work with. Before I get into the details you'll see Ive provided a graphic representation of how the architecture will be laid out.</p>
<p style="margin-bottom:0;">
<div id="attachment_12" class="wp-caption aligncenter" style="width: 430px"><a href="http://justinleider.files.wordpress.com/2008/07/architecture-overview.jpg"><img class="size-full wp-image-12" src="http://justinleider.files.wordpress.com/2008/07/architecture-overview.jpg" alt="A visual representation of a horizontal web architecture." width="420" height="300" /></a><p class="wp-caption-text">A visual representation of a horizontal web architecture.</p></div>
<p style="margin-bottom:0;">
<p style="margin-bottom:0;">Bear with me as I explain the work flow behind this graphic as it is not 100% clear from the visual representation. First off, I run <a title="Ubuntu Linux" href="http://www.ubuntu.com/" target="_blank">Ubuntu Linux</a> which is great for just about everything I need, except for creating any sort of graphics, so I apologize in advance for the lackluster graphic. As you can see, there are a few different layers: users, <a title="HA Proxy -- Load Balancing " href="http://haproxy.1wt.eu/" target="_blank">HA Proxy</a>, Apache, <a title="High performance caching system" href="http://www.danga.com/memcached/" target="_blank">Memcached</a>, <a title="SQLite -- A small fast file based database" href="http://www.sqlite.org/" target="_blank">SQLite</a> and finally MySQL labeled as databases.</p>
<p style="margin-bottom:0;">First and foremost are our beloved users, which whom without we would have no need for a website. Starting from the beginning, the users request a page from CitySquares, from there their request is passed through one of two HA Proxy servers. The sole purpose of these two machines is to load balance the incoming requests among all our Apache web servers and serve as a failsafe for one another. Once the user's request has been accepted and forwarded along to Apache we actually begin to process the request.</p>
<p style="margin-bottom:0;">The Apache servers run PHP and XCache modules. The PHP part I feel is fairly straight forward and out of the scope of this post so I will skip that part of the architecture. XCache however, is used in conjunction with and is an enhancement to PHP. More specifically XCache is an opcode optimizer and cache. It works by removing the compilation time of PHP scripts by caching the compiled and optimized state of the PHP scripts directly in the shared memory of the Apache server. This compiled version can increase page generation times by up to 500%, speeding up overall response time and reducing server load.</p>
<p style="margin-bottom:0;">Just as with all dynamic websites most if not all the actual data is stored in databases. Gone are the days of flat files with near zero processing required. Databases are the new workhorses of the web world and as such usually become the bottle neck of the overall system. CitySquares is in a somewhat unique position, nearly all our page loads have quite a bit of location and distance based processing and nearly all of this is done in our MySQL database. So while our Apache servers are sitting idle waiting for responses from their queries, the DB is preforming the brunt of the work calculating distances between objects and the like.</p>
<p style="margin-bottom:0;">We can reduce this bottleneck in a couple of different ways, the first of which is object caching. We will use Memcached to cache objects returned from the database. Say for example, we know the distance between two businesses. We know with a fair amount of certainty that those two businesses are going to be in the same place they were an hour ago, just as they were a week ago and as they will be a day from now. So we can cache this information with an expiration time of a couple days, thus saving ourselves the expense of calculating the distance between them on every page load. Of course if a user comes by and changes the location of one of these businesses, we can expire the object in cache and replace it with a newly calculated object straight from the database on the subsequent page load. These expensive queries require large table scans and mathematical formulas calculations on every row. These query results can be cached to free up the database and allow it to do what it does best. Store and retrieve data.</p>
<p style="margin-bottom:0;">In the case where we cant find the data in Memcached, either because it doesn't yet exist or has expired we will turn to our databases. We must first query a SQLite instance which is the gate keeper between Apache and the numerous databases we have. By having a separate lookup table we can essentially divide and parcel out our data sets on a table by table basis even down to an entry by entry basis. Depending on the type of data we are requesting SQLite will provide us with the location of one database or another to query for our data.</p>
<p style="margin-bottom:0;">One could argue that this just adds another layer of latency and they would be correct. However, as scalability becomes an issue you will find that adding database replication generally results in diminishing returns.  As new servers are brought online the overhead associated with replicating writes across all the replicated servers becomes choking and creates its own bottleneck. On the other hand, with a lookup table and a horizontal database architecture we don't have to worry about database replication nearly as much. You can just as easily divide your data sets into different databases. Now how you go about this varies greatly depending on your data. For CitySquares the solution turns out to be rather simple. Everything we do is location specific so it only makes sense that each data set is only as big as its parent city. Theoretically every city and all the data related to said city could reside in its own database. As you can probably guess we are only performance limited by the biggest cities, <a title="Manhattan on CitySquares" href="http://ny.citysquares.com/manhattan" target="_blank">Manhattan</a>, <a title="Brooklyn on CitySquares" href="http://ny.citysquares.com/brooklyn" target="_blank">Brooklyn</a>, etc. In these few cases we can always fall back to bigger and better servers and or replication if necessary.</p>
<p style="margin-bottom:0;">Just as our database has become a bottleneck in our current site, our search engine is also one as well, just to a lesser extent. We can take the lessons learned from our horizontal database architecture and apply it to the search engine architecture as well. By dividing our data sets into logical partitions we can keep our data from getting too large and unwieldy;  And with these smaller data sets we can reduce or remove all together the overhead associated with replicating data over multiple machines.</p>
<p style="margin-bottom:0;">While this solution sounds great, it won't be worth the effort if every time a programmer wanted to access some data they would be required to check Memcached, then SQLite and then finally MySQL for every query. In order for this to be feasible from a programmers standpoint the programmer should never have to think about this underlying architecture. This of course I will discuss in greater detail in the upcoming installments. Stay Tuned.</p>
<p style="margin-bottom:0;">
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2008/07/24/an-architecture-overview-apache-mysql-memcached-sqlite/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Turning the page &#8212; PHP, Symfony, ORM</title>
		<link>http://www.derivante.com/2008/07/18/turning-the-page-php-symfony-orm/</link>
		<comments>http://www.derivante.com/2008/07/18/turning-the-page-php-symfony-orm/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 18:23:42 +0000</pubDate>
		<dc:creator>Justin Leider</dc:creator>
				<category><![CDATA[Framework]]></category>
		<category><![CDATA[Web Architecture]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[codability]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[horizontal architecture]]></category>
		<category><![CDATA[maintainability]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[smarty]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://justinleider.wordpress.com/?p=3</guid>
		<description><![CDATA[I have come to the conclusion that I should be cataloging my work, thoughts, theories and activities for others to read and learn from my experiences as a web engineer. Let me begin by mentioning I work at a company called CitySquares and for the last year I have been working diligently on the current [...]]]></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 come to the conclusion that I should be cataloging my work, thoughts, theories and activities for others to read and learn from my experiences as a web engineer. Let me begin by mentioning I work at a company called <a title="CitySquares Online" href="http://citysquares.com" target="_blank">CitySquares</a> and for the last year I have been working diligently on the current CitySquares site.</p>
<p>This has been a great year for me as I was given the opportunity to learn the inner workings of the Drupal CMS. While <a title="Drupal CMS" href="http://drupal.org" target="_blank">Drupal</a> is a great CMS/Framework, it is inherently still a prepackaged CMS designed for things that 99% of the community needs. CitySquares unfortunately falls within that other 1%. I must say that we have accomplished quite a bit using Drupal's community modules in conjunction with our own custom written ones. However, there are plans in the works that we would like to implement but just cant within the Drupal framework.</p>
<p>Although all is not lost. With the current iteration running and stable and gaining traffic every week I have the opportunity to turn the page and begin work on the next phase of development. This is an exciting time and I will use this medium to convey the successes as well as the issues as development here continues.</p>
<p>That said, we have decided to scrap our Drupal based architecture in favor of a more extensible framework, <a title="Symfony Framework" href="http://www.symfony-project.org" target="_blank">Symfony</a>. Symfony is a PHP based OO architecture that resembles Ruby on Rails. Not only will we gain the benefit of switching to a OO style framework but we will be using Doctrine as our ORM and Smarty as our template engine.</p>
<p>The idea is that this combination of technologies will help us alleviate two of the major problems we have with Drupal, essentially scalability and codability. Ive been toying with some ideas to help eliminate these two thorns in our side that I will discuss at a later time but look forward to hearing my ideas on a full stack horizontal architecture.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.derivante.com/2008/07/18/turning-the-page-php-symfony-orm/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! -->