<?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>Views From The Hill &#187; Zend Framework</title>
	<atom:link href="http://dustint.com/archives/tag/zend-framework/feed" rel="self" type="application/rss+xml" />
	<link>http://dustint.com</link>
	<description>Tales Of A (Former) SFU Computing Scientist</description>
	<lastBuildDate>Thu, 17 Jun 2010 20:14:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Build an API for any website with Web-Scraping</title>
		<link>http://dustint.com/archives/184</link>
		<comments>http://dustint.com/archives/184#comments</comments>
		<pubDate>Sun, 16 May 2010 07:00:21 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Screen Scraping]]></category>
		<category><![CDATA[Web Scraping]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=184</guid>
		<description><![CDATA[There are a lot of web-sites out there, with a lot of data on them. Sometimes you are building a killer web-app and you just have to have some data off a certain site. The problem is, that particular site doesn&#8217;t have an API that you can just plug into! Never fear, using some simple [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of web-sites out there, with a lot of data on them. Sometimes you are building a killer web-app and you just have to have some data off a certain site. The problem is, that particular site doesn&#8217;t have an API that you can just plug into! Never fear, using some simple tools, combined with the Zend Framework you can create your own web-scraping (screen-scraping) API in no time.</p>
<p>Before I continue, I should mention that, not only is it impolite, but quite possibly illegal to take the content of a third party site without the owners permission or knowledge.</p>
<p>To accomplish our task we need some open-source tools:</p>
<ul>
<li><a title="Zend Framework" href="http://framework.zend.com">Zend Framework</a> (Required)</li>
<li><a href="http://quixapp.com/">Quix</a> (Recommended)</li>
<li><a title="Dojo Toolkit" href="http://www.dojotoolkit.org/">Dojo Toolkit</a> (Recommended)</li>
</ul>
<p>Our basic strategy is this:</p>
<ol>
<li> Find a target page with some cool content</li>
<li> Find the CSS Selector (or X-path) of the element we want to scrape</li>
<li> Verify the selector using Dojo</li>
<li> Build a Zend_Service object to fetch the cool content to PHP</li>
</ol>
<h2>Step 1: Finding the cool page</h2>
<p>Say I am a developer and I really want to get the outward facing IP of the machine that my PHP script is running on. If there is a router or proxy in between my machine and the Internet, this can be non trivial. As a solution I decide to use the service <a href="http://www.whatismyip.com/">http://www.whatismyip.com/</a></p>
<h2>Step 2: Finding the CSS3 Selector for the element</h2>
<p>Its pretty obvious which element we want to get the selector for. If you are feeling clever you can simply read the code or use a DOM inspector to figure out what the query is on your own. However, selectorgaget.com provides a cool tool that will allow you to point and click to determine the appropraite selector. You can get a bookmarklet directly from their site, or you can get the much more powerful Quix bookmarklet which includes the selectorgaget and a bunch of other cool tools.</p>
<p>If you decided on Quix (I know I did), click on the bookmarklet and enter &#8220;sg&#8221; in the command box. The selectorgaget should load up and as you move your mouse around the screen it should highlight different DOM nodes. We want the top one, so click on the text &#8220;Your IP&#8230;&#8221; and, checking out the path, we see that it is a rather boring h1.</p>
<h2>Step 3: Validation via Dojo</h2>
<p>I like to validate the path before taking it over to Zend. I use a Dojo and firebug lite bookmarklet which injects a debugging version of dojo into any page via the AOL CDN. To add this bookmarket drag <a  href="javascript:(function(){%20var%20d=document;%20var%20h=d.getElementsByTagName('HEAD')[0];%20var%20s=d.createElement('script');%20s.type='text/javascript';%20s.src='http://o.aolcdn.com/dojo/1.4.0/dojo/dojo.xd.js.uncompressed.js';%20h.appendChild(s);%20})()">Inject Dojo</a> into your bookmarks toolbar. In the debugging console that pops up, enter dojo.query(&#8216;h1&#8242;); and you should see the h1 DOM element being returned.</p>
<h2>Step 4: Moving it all to PHP</h2>
<p>Now that we have successfully found our CSS3 selector path, we can move over to PHP and come up with a new Zend_Service component. Our approach will be to extend Zend_Service_Abstract, and implement some custom methods to preform the screen scrape.</p>
<p>The finished class looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> WhatsMyIpService <span style="color: #000000; font-weight: bold;">extends</span> Zend_Service_Abstract
<span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * The service endpoint.
	 * This is where Zend_Http_Client will navigate
	 * to fill service requests
	 * @var string
	 */</span>
	protected <span style="color: #000088;">$_endpoint</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://whatismyip.com'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * handle to the client
	 * @var Zend_Http_Client
	 */</span>
	protected <span style="color: #000088;">$_client</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_client <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getHttpClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Method to get the external IP of the computer / server
	 * script is running on
	 * @return string
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getMyIp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">//reset the client parameters, set the URL to whatismyip.com</span>
		<span style="color: #666666; font-style: italic;">//and actually preform the request</span>
		<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_client
			<span style="color: #339933;">-&gt;</span><span style="color: #004000;">resetParameters</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">-&gt;</span><span style="color: #004000;">setUri</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_endpoint<span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">-&gt;</span><span style="color: #004000;">request</span><span style="color: #009900;">&#40;</span>Zend_Http_Client<span style="color: #339933;">::</span><span style="color: #004000;">GET</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//check to make sure that the result isnt a HTTP error</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isError</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Client returned error: '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		try<span style="color: #009900;">&#123;</span>
			<span style="color: #666666; font-style: italic;">//setup the query object with the result body (HTML page)</span>
			<span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Dom_Query<span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBody</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #000088;">$domCollection</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'h1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>catch<span style="color: #009900;">&#40;</span>Zend_Dom_Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Error Loading Document: '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//check to make sure the query return a result</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$domCollection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cannot find DOM Element'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//get the titlestring from the nodevalue</span>
		<span style="color: #000088;">$titleString</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$domCollection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">current</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nodeValue</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//now we should have the content of h1 stored in the titleString</span>
		<span style="color: #666666; font-style: italic;">//it should read something like &quot;Your IP Address Is: xxx.xxx.xxx.xxx&quot;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Now we will parse out the IP address using regular expressions</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/([\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$titleString</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Unable to parse IP from page'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I hope that the script is sufficiently commented, but to summarize:</p>
<p>In the constructor, we get an local instance of a Zend_Http_Client object. Clone() is used to prevent any other Zend_Service objects from polluting our client with their own requests.</p>
<p>In the getMyIp() method, we first setup and preform the request (using the fluid interface provided by Zend_Http_Client). Notice how we reset the parameters: In this case its not actually necessary as we aren&#8217;t passing any parameters, but it is good habit to get into in case in the future we expand this class to include GET or POST parameter passing.  </p>
<p>Next, we examine what the HTTP client has passed back to us. Hopefully, if nothing has gone wrong, it is a HTML string representation of the page at whatismyip.com. Some basic checks are preformed to ensure that no HTTP errors have occurred, and then we instantiate a Zend_Dom_Query object which provides both CSS  and Xpath selectors.</p>
<p>Finally, after running the CSS selector query, we check to ensure we got a DOM element back, get its value and parse out the IP using Regular expressions. Its pretty impressive what can be done in <70 lines of code with the Zend Framework.</p>
<p>To run this class, we could create a directory structure as follows:<br />
library <- Includes Zend framework<br />
WhatsMyIpService.php <- The above class<br />
getIp.php <- php file including the following:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">set_include_path</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span>PATH_SEPARATOR<span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #990000;">realpath</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/library'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #990000;">get_include_path</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/** Zend_Loader_Autoload **/</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Loader/Autoloader.php'</span><span style="color: #339933;">;</span>
Zend_Loader_Autoloader<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFallbackAutoloader</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$service</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WhatsMyIpService<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMyIp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The first couple of lines gets the library on the include path, the second block sets up autoloading so we don&#8217;t have to manually include files, and the final lines instantiates the class and calls the method.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/184/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Translink Zend Framework API</title>
		<link>http://dustint.com/archives/66</link>
		<comments>http://dustint.com/archives/66#comments</comments>
		<pubDate>Wed, 16 Sep 2009 09:30:01 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zext]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=66</guid>
		<description><![CDATA[Translink is the local public transit provider for beautiful Vancouver, Canada. The system consists of Buses, Boats and Trains. Translink released an Iphone app some time ago that allows the lookup of bus information. Michael Weisman was kind enough to write about the &#8220;hidden&#8221; api that is used by the Iphone app to preform AJAX [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://translink.bc.ca" target="_blank">Translink</a> is the local public transit provider for beautiful Vancouver, Canada. The system consists of Buses, Boats and Trains. Translink released an Iphone app some time ago that allows the lookup of bus information. Michael Weisman was kind enough to <a href="http://www.mweisman.com/transit.html">write</a> about the &#8220;hidden&#8221; api that is used by the Iphone app to preform AJAX calls.<br />
<span id="more-66"></span></p>
<p>The Zend Framework based API that I have written duplicates the functionality described on Micheal&#8217;s page and exposes the API functionality to PHP applications.</p>
<p>Please keep in mind that as this is an unofficial API, Translink may not want their data being used without their permission. Please contact Translink before making use of this API on a production site.</p>
<h1>Example Usage</h1>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$translink</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zext_Service_Translink<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get the route directions for the 135</span>
<span style="color: #000088;">$directions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$translink</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouteDirections</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'135'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
Zend_Debug<span style="color: #339933;">::</span><span style="color: #004000;">dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$directions</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get the east-bound stops for the 135</span>
<span style="color: #000088;">$stops</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$translink</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouteStops</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'135'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'east'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
Zend_Debug<span style="color: #339933;">::</span><span style="color: #004000;">dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stops</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get the details for an arbitrary stop</span>
Zend_Debug<span style="color: #339933;">::</span><span style="color: #004000;">dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$translink</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStopDetails</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">51845</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//get the latitude and longitude for a stop</span>
Zend_Debug<span style="color: #339933;">::</span><span style="color: #004000;">dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$translink</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStopLocation</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">51845</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//get the stops near a given latitude and longitude</span>
Zend_Debug<span style="color: #339933;">::</span><span style="color: #004000;">dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$translink</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLocationStops</span><span style="color: #009900;">&#40;</span><span style="color:#800080;">49.25344</span><span style="color: #339933;">,-</span><span style="color:#800080;">123.167895</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h1>Download &amp; Install</h1>
<p>Download the following file:<br />
<a href="http://dustint.com/wp-content/uploads/2009/08/Zext_Service_Translink.zip">Zext_Service_Translink</a><br />
Add it to your library path (same folder that Zend of the Zend framework resides in) if you have autoloading enabled.</p>
<p>I will try to respond to any problems in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/66/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BC Lottery Corporation API</title>
		<link>http://dustint.com/archives/93</link>
		<comments>http://dustint.com/archives/93#comments</comments>
		<pubDate>Wed, 02 Sep 2009 09:30:05 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zext]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=93</guid>
		<description><![CDATA[The British Columbia Lottery Corporation has an unpublished API that they use to pull data down for the flash application on their home page. The Zext PHP API exposes functionality to query the most resent winning numbers from the BCLC website, as well as retrieve current jackpot estimates for the main lotteries in this province. [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.bclc.com/">British Columbia Lottery Corporation</a> has an unpublished API that they use to pull data down for the flash application on their home page. The Zext PHP API exposes functionality to query the most resent winning numbers from the BCLC website, as well as retrieve current jackpot estimates for the main lotteries in this province.<br />
<span id="more-93"></span><br />
Again, as with most of the API&#8217;s I have been publishing lately, this API relies on undocumented and unsupported functionality which may break or become unavailable at any time. Furthermore, there are likely licensing issues involved with unauthorized use of BCLC data, so proceed with caution if you plan on using this API in a production app.</p>
<h1>Example Usage</h1>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$bclc</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zext_Service_BCLC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get the results of the latest 649 results</span>
<span style="color: #000088;">$bclc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get649Results</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//get the estimated jackpot size for the latest 649 results</span>
<span style="color: #000088;">$bclc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get649Estimate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get the 649 Extra numbers for the latest draw</span>
<span style="color: #000088;">$bclc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get649ExtraResults</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>There are many other functions that the API exposes. Take a look through the source to view them all.</p>
<h1>Download &#038; Install</h1>
<p>Download the following file:<br />
<a href='http://dustint.com/wp-content/uploads/2009/08/Zext_Service_BCLC.zip'>Zext_Service_BCLC</a><br />
Add it to your library path (same folder that Zend of the Zend framework resides in) if you have autoloading enabled.</p>
<p>I will try to respond to any problems in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/93/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Framework Doctrine Model Autoloader</title>
		<link>http://dustint.com/archives/137</link>
		<comments>http://dustint.com/archives/137#comments</comments>
		<pubDate>Wed, 26 Aug 2009 09:30:42 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Autoload]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=137</guid>
		<description><![CDATA[There have been several tutorials outlining how to autoload Doctrine Models using the Zend_Loader_Autoloader. However, none of these have permitted Zend / PEAR style naming conventions for models. I prefer to use these conventions because, although it makes my model names longer, the &#8220;name-spacing&#8221; gives a certain degree of organization and order to the application. [...]]]></description>
			<content:encoded><![CDATA[<p>There have been several tutorials outlining how to autoload Doctrine Models using the Zend_Loader_Autoloader. However, none of these have permitted Zend / PEAR style naming conventions for models. I prefer to use these conventions because, although it makes my model names longer, the &#8220;name-spacing&#8221; gives a certain degree of organization and order to the application.<br />
<span id="more-137"></span><br />
For example, lets say we have two classes (and two tables) in our database. The first class is a very simple person model. A person has an Id, which is used at the primary key, and a name. This person class would be described in YAML notation as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">App_Model_Person:
 tableName: T_person
 columns:
  id: integer
  name: string(64)</pre></div></div>

<p>People have addresses. One person may have more than one address (billing, mailing, physical, for example). Therefore, we need a second, person address table similar to the following:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">App_Model_Person_Address:
 tableName: T_person_address
 package: Person
 columns:
  person_id: integer
  address: string</pre></div></div>

<p>Notice that the App_Model_Person_Addres model is in the <em>Person</em> package. This is done to ensure that it will be placed in the person subfolder, so the final path of this class will be App/Model/Person/App_Model_Person_Address.php</p>
<p>Before, using the doctrine command line tool to generate the classes, we must make sure that we are going to generate the models in the appropriate location. Assuming that we have an application library on the include path (eg: library/ is on the include path and it has a folder App in it), then we want Doctrine generating the models in the <em>library/App/Model</em> folder. This can be done by setting the <em>models_path</em> to the proper location. Eg:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">new</span> Doctrine_Cli<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
<span style="color: #339933;">...,</span>
<span style="color: #0000ff;">'models_path'</span>         <span style="color: #339933;">=&gt;</span>  APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/library/App/Model'</span><span style="color: #339933;">,</span>
<span style="color: #339933;">...</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The main problem with the auto-generated classes produced by the Doctrine_Cli is the filename of the php file that is generated. For, example, the full path of the generated App_Model_Person class will be <em>library/App/Model/App_Model_Person.php</em>; however, according to Zend conventions it should be <em>library/App/Model/Person.php</em>. </p>
<p>The Doctrine Model Autoloader provided below attempts to solve these problems by detecting when a Doctrine Model is being loaded, and then generating the appropriate path (with the full class name acting as the filename). To complicate matters, there are some special cases for base-classes and package classes as well, specifically that they may have <em>Base</em> or <em>Package</em> prefixing the name of the class. The Model autoloader addresses this by detecting the presence of these terms using regular expressions and tweaking the generation of the paths accordingly.</p>
<p>It is very simple to use the Doctrine Model Autoloader class. Simply instantiate it, passing it the prefix of the Doctrine Model namespace. In this case it would be <em>App_Model_</em>. Don&#8217;t forget the trailing underscore (&#8220;_&#8221;), however the class should detect that its missing and add it in for you if you do. </p>
<p>An example usage for the above case would be simply:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$doctrineAutoloader</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zext_Loader_Autoloader_DoctrineModel<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'App_Model_'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Upon instantiation, the autoloader registers itself with the Zend_Loader_Autoloader for the passed namepace, so no further setup is required.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Zext_Loader_Autoloader_DoctrineModel implements Zend_Loader_Autoloader_Interface
<span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * The namespace of the models
	 * @var string
	 */</span>
	protected <span style="color: #000088;">$_namespace</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Whether or not to suppress file not found warnings
     * @var bool
     */</span>
	protected <span style="color: #000088;">$_suppressNotFoundWarnings</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * 
	 * @param string $modelNamespace	The namespace of the model to load. Eg: 'Zext_Model_'
	 * @param boolean $quiet			If this is true, suppresses warnings if the file isn't found
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$modelNamespace</span><span style="color: #339933;">,</span> <span style="color: #000088;">$quiet</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strrpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$modelNamespace</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'_'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">!=</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$modelNamespace</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$modelNamespace</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'_'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace <span style="color: #339933;">=</span> <span style="color: #000088;">$modelNamespace</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_suppressNotFoundWarnings <span style="color: #339933;">=</span> <span style="color: #000088;">$quiet</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Initializes Zend_Loader_Autoloader, pushing the doctrine autoloader onto the autoloading stack
	 * @return void
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$namespaces</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
			<span style="color: #0000ff;">'Package'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace<span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'Base'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace<span style="color: #339933;">,</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace
		<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$autoloader</span> <span style="color: #339933;">=</span> Zend_Loader_Autoloader<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$namespaces</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$namespace</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$autoloader</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pushAutoloader</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #000088;">$namespace</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * (non-PHPdoc)
	 * @see tests/library/Zend/Loader/Autoloader/Zend_Loader_Autoloader_Interface#autoload($class)
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> autoload<span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">class_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> interface_exists<span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
        <span style="color: #666666; font-style: italic;">//Check to see if we are loading a package / base</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/(?P&lt;prefix&gt;.+)'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace  <span style="color: #339933;">.</span> <span style="color: #0000ff;">'(?P&lt;class&gt;.+)/mx'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'prefix'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'prefix'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'package'</span><span style="color: #339933;">:</span>
					<span style="color: #000088;">$classPath</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_loadPackage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'class'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
&nbsp;
				<span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'base'</span><span style="color: #339933;">:</span>
					<span style="color: #000088;">$classPath</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_loadBase<span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'class'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$classPath</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getPath<span style="color: #009900;">&#40;</span>
				<span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">strrpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'_'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
				<span style="color: #000088;">$className</span>
			<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_suppressNotFoundWarnings<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        	<span style="color: #339933;">@</span>Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadFile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$classPath</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadFile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$classPath</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">class_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>interface_exists<span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        	<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Gets the correct path for loading packages
	 * 
	 * @param $className
	 * @return string
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _loadPackage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$package</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'_'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getPath<span style="color: #009900;">&#40;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace <span style="color: #339933;">.</span> <span style="color: #0000ff;">'packages_'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$package</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'_'</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'Package'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace <span style="color: #339933;">.</span> <span style="color: #000088;">$className</span>
		<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Gets the correct path for loading bases
	 * 
	 * @param $className
	 * @return string
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _loadBase<span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$package</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'_'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getPath<span style="color: #009900;">&#40;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace <span style="color: #339933;">.</span> <span style="color: #000088;">$package</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'_generated_'</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'Base'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_namespace <span style="color: #339933;">.</span> <span style="color: #000088;">$className</span>
		<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Gets the classpath from an _ separated path and the classname
	 * 
	 * @param string $path
	 * @param string $name
	 * @return string
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _getPath<span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #339933;">,</span> <span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'_'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">DIRECTORY_SEPARATOR</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'.php'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/137/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Epguides.com Zend Framework API</title>
		<link>http://dustint.com/archives/53</link>
		<comments>http://dustint.com/archives/53#comments</comments>
		<pubDate>Thu, 20 Aug 2009 05:05:33 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=53</guid>
		<description><![CDATA[Lately I have been writing Service API&#8217;s for Zext, my Zend Framework library extension. I plan on publishing some of the more useful ones over the next couple of months on my blog. The first of the series is the Epguides.com API. Epguides.com is a listing of TV show episode listings. This can be useful, [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I have been writing Service API&#8217;s for Zext, my Zend Framework library extension. I plan on publishing some of the more useful ones over the next couple of months on my blog. The first of the series is the Epguides.com API.</p>
<p><span id="more-53"></span>Epguides.com is a listing of TV show episode listings. This can be useful, for example, if you are downloading episodes from the internet and want to automatically name the files. Alternatively, if you are hosting a website this API could expose current episode listings for shows of your choice.</p>
<p>The API consists of three parts:</p>
<ol>
<li>Zext_Service_Epguides &#8211; The basic service class. Has one public method: <em>getShowObject($showName)</em></li>
<li>Zext_Service_Epguides_Show &#8211; The objet that is returned by <em>getShowObject($showName)</em></li>
<li>Zext_Service_Epguides_Episode &#8211; Individual episode objects that reside in the show object</li>
</ol>
<h1>Zext_Service_Epguides</h1>
<p>Fortunately, Epguides.com has a very regular naming scheme for their pages. The basic pattern is http://epguides.com/{<em>show_name</em>}/ where <em>show_name</em> is the name of the show, in lowercase, with whitespace and special characters removed. This can be accomplished using the following regex:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$showName</span> <span style="color: #339933;">=</span> <span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/[^\w]/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$showName</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Rather unfortunately, epguides.com doesn&#8217;t follow this naming scheme for all shows. For example, &#8220;The Office&#8221; (North American Version) is called &#8220;office_us&#8221;. Therefore, when querying epguides.com using this API you want to be using the string that identifies the proper URL of the desired show. The API will generate the correct URL for shows that conform to the regular naming scheme, but you must use the epguides.com naming conventions for show names that are exceptions to the rules.</p>
<p>After the API generates the URL for a given show, it fetches the corresponding page from Epguides.com and parses it. The parsing is done by a combination of domnode selection using the DOMDocument object and regular expressions. Fell free to read the source for more details.</p>
<p>The parser returns an array which is then passed to the Zext_Service_Epguides_Show() object.</p>
<p>The Show and episode classes are fairly straight forward and mostly act as containers to provide some convenience functions. I hope you can get a fairly good idea of how to work with them by viewing the below usage example.</p>
<h1>Example Usage</h1>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$epguidesAPI</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zext_Service_Epguides<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Gets a show object for The Office</span>
<span style="color: #000088;">$show</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$epguidesAPI</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getShowObject</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'office_us'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Print out all the episodes as strings.</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$show</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllEpisodes</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$episode</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$episode</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Get the 10th episode of the 2nd season</span>
<span style="color: #000088;">$episode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$show</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEpisode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h1>Download and Install</h1>
<p>Download the following file:<br />
<a href="http://dustint.com/wp-content/uploads/2009/08/Zext_Service_Epguides.zip">Zext_Service_Epguides</a><br />
Add it to your library path (same folder that Zend of the Zend framework resides in) if you have autoloading enabled.</p>
<p>I will try to respond to any problems in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/53/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Per Module Zend_Layout</title>
		<link>http://dustint.com/archives/28</link>
		<comments>http://dustint.com/archives/28#comments</comments>
		<pubDate>Wed, 06 Aug 2008 03:18:53 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Controller_Plugin]]></category>
		<category><![CDATA[Zend_Layout]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=28</guid>
		<description><![CDATA[Sometimes when you are building a web application, you want to use different layouts for different parts of the site. For example, in a content management system, you may want one layout for normal users and another, completely different layout for site administrators. Assuming that you have the standard zend directory structure, you will have [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes when you are building a web application, you want to use different layouts for different parts of the site. For example, in a content management system, you may want one layout for normal users and another, completely different layout for site administrators. <span id="more-28"></span></p>
<p>Assuming that you have the standard zend directory structure, you will have something like this:</p>
<pre>/application
  /admin
    /controllers
    /layouts
    /views
  /default
    /controllers
    /layouts
    /views
  /feeds
    /controllers
    /views</pre>
<p>Or something of the sort. When the user is in the admin section we want to use the layout folder from /admin, and when they are in the default section or in the feeds section of the site we would like to use the layout folder from /default.</p>
<p>We could simply go through all the controllers in the admin section and set the layout path in the init or preDisptach function:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	Zend_Layout<span style="color: #339933;">::</span><span style="color: #004000;">getMvcInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLayoutPath</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'../application/admin/layouts'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This may work well for this simple example. However, every time we wish to add a controller to the admin section it would be necessary to setup the layout path and if ever we want to change the layout path for the admin module, there would be a lot of search-replacing.</p>
<p>A Much better solution is to write a plugin for the Zend Front controller. This plugin extends the Zend_Controller_Plugin_Abstract type and will be run each time the front controller is invoked, before anything is rendered.</p>
<p>Our plugin must have some very basic functionality:</p>
<ol>
<li>Ability to register a layout for use with a specified module</li>
<li>Ability to fall back to the default layout if there is no layout registered for the current module</li>
</ol>
<p>The Layout Plugin is as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Module_LayoutPlugin <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Array of layout paths associating modules with layouts
	 */</span>
	protected <span style="color: #000088;">$_moduleLayouts</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Registers a module layout.
	 * This layout will be rendered when the specified module is called.
	 * If there is no layout registered for the current module, the default layout as specified
	 * in Zend_Layout will be rendered
	 * 
	 * @param String $module		The name of the module
	 * @param String $layoutPath	The path to the layout
	 * @param String $layout		The name of the layout to render
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> registerModuleLayout<span style="color: #009900;">&#40;</span><span style="color: #000088;">$module</span><span style="color: #339933;">,</span> <span style="color: #000088;">$layoutPath</span><span style="color: #339933;">,</span> <span style="color: #000088;">$layout</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_moduleLayouts<span style="color: #009900;">&#91;</span><span style="color: #000088;">$module</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
			<span style="color: #0000ff;">'layoutPath'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$layoutPath</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'layout'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$layout</span>
		<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_moduleLayouts<span style="color: #009900;">&#91;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_moduleLayouts<span style="color: #009900;">&#91;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getModuleName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #000088;">$layout</span> <span style="color: #339933;">=</span> Zend_Layout<span style="color: #339933;">::</span><span style="color: #004000;">getMvcInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$layout</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMvcEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$layout</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLayoutPath</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'layoutPath'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'layout'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
					<span style="color: #000088;">$layout</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLayout</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'layout'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The $_moduleLayouts property maintains the mapping between modules and layouts.</p>
<p>The registerModuleLayout function allows us to register a layoutpath and an (optional) layout name for a module. </p>
<p>The actual magic happens in the preDispatch function (which is called by the front controller before dispatching the request). The function checks to see if there is a layout set for the current module; if there is, it switches the layout path to use the module-specific path. Next it checks to see if there is a layout name associated with the layout registered for this module. If there is, it uses it, otherwise it falls back to the default layout name.</p>
<p>In our bootstrapper file (html/index.php) we must setup the default layout and module layout paths and then register the plugin with the front controller. The following code snippit is only a sliver of the bootstrapper and assumes that $controller is an instance of Zend_Controller_Front (eg: $controller = Zend_Controller_Front::getInstance();)</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//setup the layout</span>
Zend_Layout<span style="color: #339933;">::</span><span style="color: #004000;">startMvc</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'layoutPath'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'../application/default/layouts'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'layout'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'main'</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$layoutModulePlugin</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Module_LayoutPlugin<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$layoutModulePlugin</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerModuleLayout</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'admin'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'../application/admin/layouts'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerPlugin</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$layoutModulePlugin</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>It is important to setup the default layout so the plugin has a layout to fall back to if no module-specific layout is registered. </p>
<p>I hope that this tutorial has served as a quick and easy introduction to Zend Front Controller plugins and module-specific layouts.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/28/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Fakemail for Developers</title>
		<link>http://dustint.com/archives/27</link>
		<comments>http://dustint.com/archives/27#comments</comments>
		<pubDate>Sat, 07 Jun 2008 07:34:18 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=27</guid>
		<description><![CDATA[The other day when I was setting up email notifications for a Zend Framework application, I stumbled across Fakemail. From the developers website: fakemail is a fake mail server that captures emails as files for acceptance testing. This avoids the excessive configuration of setting up a real mail server and trying to extract mail queue [...]]]></description>
			<content:encoded><![CDATA[<p>The other day when I was setting up email notifications for a Zend Framework application, I stumbled across Fakemail.</p>
<p>From the developers website:</p>
<blockquote><p>fakemail is a fake mail server that captures emails as files for acceptance testing. This avoids the excessive configuration of setting up a real mail server and trying to extract mail queue content.</p></blockquote>
<p>I am quite impressed with this handy little script (written in both Python and Perl), as it works exactly as advertised: taking out the time required to properly configure a SMTP server and saving the hassle of having dozens of test messages showered across inboxes. Instead of forwarding emails on to their recipients, it simply saves a raw copy of the email to the specified directory.</p>
<p>The script has a windows installer that bundles the script with python and will run on all flavors of Linux and Unix assuming that they have perl or python installed.</p>
<p>To configure Zend_Mail use fakemail place the following in your bootstrapper or common config file:<br />
[php]Zend_Mail::setDefaultTransport(new Zend_Mail_Transport_Smtp(&#8216;localhost&#8217;,array(<br />
&#8216;port&#8217; =&gt; 10025<br />
)));[/php]</p>
<p>The &#8216;localhost&#8217; variable is the address of the computer that fakemail is running on (likely the local machine). The port number is the port that is specified when fakemail is run on the command line.</p>
<p>For more information about fakemail, binaries, and a usage guide. Visit the developers website at Sourceforce: <a href="http://www.lastcraft.com/fakemail.php">http://www.lastcraft.com/fakemail.php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/27/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cache-Control with Zend Framework</title>
		<link>http://dustint.com/archives/25</link>
		<comments>http://dustint.com/archives/25#comments</comments>
		<pubDate>Fri, 06 Jun 2008 02:45:37 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Cache-Control]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=25</guid>
		<description><![CDATA[Today I was optimizing a site that uses heavy PHP and Ajax. I wanted to reduce the amount of data that was being sent from the server. To put this in perspective, if there were no cache hits in a page load there would be a total of 755 KB pulled down over 123 requests. [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was optimizing a site that uses heavy PHP and Ajax. I wanted to reduce the amount of data that was being sent from the server. To put this in perspective, if there were no cache hits in a page load there would be a total of 755 KB pulled down over 123 requests.<br />
<span id="more-25"></span><br />
The first step was throwing a .htaccess into the dojo folder that sets the Cache-Control header on the library files being pulled down.</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_expires.c&gt;
     <span style="color: #00007f;">Header</span> set Cache-Control <span style="color: #7f007f;">&quot;max-age=3600, public&quot;</span>
&lt;/<span style="color: #000000; font-weight:bold;">IfModule</span>&gt;</pre></div></div>

<p>The above checks to ensure the mod_expires module is loaded in apache, and if it is the Cache is set to expire 3600 seconds from now: 1 hour. Furthermore, the page can be cached in a publicly accessible (shared) cache.</p>
<p>Getting caching working with Zend was a little more challenging. By default Zend (or PHP) writes caching information to headers disabling caching. However, the code snippit below (to be placed inside an Action Controller) blanks out the expires header, sets the cache-control header so that the page expires in one hour, and blanks out the Pragma header. </p>
<p>The expires header allows the server to specify a date when the cache expires (Rather than setting the max-age offset) and the Pragma indicates if the page can be cached in a proxy. I found, with Firefox 3, if Expires and Pragma weren&#8217;t blanked out, they would take preference over the Cache-Control header, disabling caching of the page.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Expires'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cache-Control'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'public'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cache-Control'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'max-age=3800'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Pragma'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>After the addition of caching, the page load was reduced to 8Kb of data pulled down over 9 requests: about a 90% optimization.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/25/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Zend JSON-RPC with Dojo Howto</title>
		<link>http://dustint.com/archives/20</link>
		<comments>http://dustint.com/archives/20#comments</comments>
		<pubDate>Tue, 03 Jun 2008 02:50:54 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[RPC]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=20</guid>
		<description><![CDATA[I have been using the Dojo toolkit as my Javascript library of choice since back in early 2006 when it was still around version 0.4. Since then, the project has made tremendous strides including the release of version 1.0 and 1.1 with 1.2 on the way. At the beginning of 2008 I started using the [...]]]></description>
			<content:encoded><![CDATA[<p><!--[if !mso]></p>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<p><![endif]--><!--[if gte mso 9]><xml> Normal   0   false            false   false   false      EN-CA   X-NONE   X-NONE                                                     MicrosoftInternetExplorer4 </xml><![endif]--><!--[if gte mso 9]><xml> </xml><![endif]--> <!--[if gte mso 10]></p>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<p><![endif]--></p>
<p>I have been using the Dojo toolkit as my Javascript library of choice since back in early 2006 when it was still around version 0.4. Since then, the project has made tremendous strides including the release of version 1.0 and 1.1 with 1.2 on the way. At the beginning of 2008 I started using the Zend Framework to build MVC PHP applications and, with the release of 1.5, it has become my PHP framework of choice.</p>
<p>To my delight, the Zend Framework and Dojo have recently <a href="http://dojotoolkit.org/2008/05/21/announcing-zend-framework-integration-dojo-1-x-0">announced</a> a partnership which will lead to tighter integration of these two great open source frameworks.</p>
<p>One of the most exciting additions to the Zend Framework is the <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Json_Server+to+support+JSON-RPC">Zend_Json_Server support for JSON-RPC</a>. I have been using JSON-RPC with Dojo for quite some time and, up until now, it has been challenging to find a design pattern that plays nice with the Model View Controller implementation in the Zend Framework. However, with the addition of the Zend_Json_Server this is no longer the case.<span id="more-20"></span></p>
<h2>Prerequisites:</h2>
<p>This tutorial assumes you are familiar with developing in PHP and javascript and are experienced with dojo and the Zend Framework using the MVC paradigm.</p>
<h2>Common Pitfalls</h2>
<ul class="unIndentedList">
<li> Absolute paths are used in the code examples. Ensure that you modify them to reflect your server&#8217;s directory structure. This tutorial assumes that you are working with a ZF project whose /html/ directory corresponds to the root of your webserver</li>
<li> Ensure you place a .htaccess file in /html/scripts/ that disables the re-write engine. If you fail to do this step, when trying to load dojo libraries, ZF will be trying to find controllers that match the requests and throwing exceptions.</li>
</ul>
<h2>Patching Zend Framework</h2>
<p>At the time of writing, the Json-RPC component has not been accepted into the Zend Framework (although it will be soon). To get the Zend Framework (ZF) working with Json-RPC we must download code from the incubator area of SVN. If you don&#8217;t know how to use a SVN client to check out code, read about it <a href="http://framework.zend.com/manual/en/introduction.installation.html">here</a>. Download the current version of ZF and then, using an SVN client, download <a href="http://framework.zend.com/svn/framework/standard/incubator/library/Zend/Json/">http://framework.zend.com/svn/framework/standard/incubator/library/Zend/Json/ </a>and place it in the json directory of your local copy of ZF.</p>
<h2>Setting up the Directories</h2>
<p>For the purpose of this tutorial I will be using code and examples from <a href="../../../../../nickel">Nickel</a>: the application that will eventually run SFU Bookswap V.3. I use a fairly standard MVC directory structure as recommended by the ZF docs:</p>
<pre>application
	|-default
	|-controllers
	|-views
html
	|-images
	|-scripts
		|-nickel
			|-RPC
library
	|-Nickel
		|-Models
		|-RPC
	|-Zend
		| .... Framework checkout
</pre>
<p>The reasoning behind placing the Nickel folder in the library is so we can use Zend_Loader to load classes on demand. Also, as a condition of this, the classes in the Nickel folder follow the ZF naming convention: so, say, the class for a book model would be named, Nickel_Model_Book.</p>
<p>Similarly, there is a corresponding directory structure in the scripts folder. This is to be used with the Dojo packaging system. So, to access the RPC handle for the book model we would call a function such as nickel.rpc.book.getAuthor()</p>
<h2>Creating the RPC Controller</h2>
<p>The next step is to actually create the RPC controller. I have created a file in /application/default/controllers/RpcController.php which contains the RpcController action controller class. RpcController has two actions: one which will return the SMD (simple method declaration) to dojo when the JSON-RPC object is instantiated. The second action, the service action, actually processes the RPC request and returns the result. So, we have:</p>
<pre>/application/default/controllers/RpcController.php
[php]<?php
class RpcController extends Zend_Controller_Action {

	public function smdAction(){
		$class = $this->_getParam('class');

		$server = new Zend_Json_Server();

		$server->getServiceMap()->setDojoCompatible(true);
		$server->getServiceMap()->setTransport('POST')
       		->setTarget($this->getHelper('url')->url(array('controller'=>'rpc', 'action'=>'service')))
       		->setId($this->getHelper('url')->url(array('controller'=>'rpc', 'action'=>'service'))); 

       	$server->setClass($class);

       	$this->view->data = $server->getServiceMap();
		$this->render('service');
	}

	public function serviceAction(){
		$class = $this->_getParam('class');

		$server = new Zend_Json_Server();
		$server->setClass($class);
		$server->setAutoEmitResponse(true);

		$server->handle();
	}
}[/php]
</pre>
<p>The smd Action takes ‘class&#8217; as a parameter. This is the name of the class that we wish to expose via Json-RPC, such as Nickel_Rpc_Book. Please note the function call setDojoCompatible(true) which forces the server to generate dojo-compatible SMD definitions. The target function call sets the target of the function calls (the service url) to the service action defined below.</p>
<p>The service action simply processes the RPC request by calling the specified function with the sent parameters.</p>
<p>There is a fairly large security hole opened by this implementation. Since any value can be passed to the ‘class&#8217; argument, it is possible to remotely call functions for any class that can be auto-loaded. A ‘safer&#8217; implementation would simply concatenate the class parameter with &#8220;Nickel_Rpc_&#8221;. This way is less likely that an attacker could compromise your server by calling a dangerous function.</p>
<h2>Writing a RPC Class</h2>
<p>Now that we have the RPC server set up we need some classes in Nickel_RPC to call. For the purpose of this example we will use a very simple Book class that has basic functionality:</p>
<pre>/library/Nickel/Model/Book.php
[php]<?php
class Nickel_RPC_Book {
	public static function simpleEcho(){
		return “Hello World”;
	}
	public static function getTitle($bookId){
		$book = new Nickel_Model_Book($bookId);
		return $book->getTitle();
	}
	public static function setTitle($bookId, $title){
		$book = new Nickel_Model_Book($bookId);
		$book->setTitle($title);
		$book->update();
		return true;
	}
}
[/php]</pre>
<p>In the above RPC class, in addition to the simpleEcho function, we have two static functions: one that reads the title from the Book Model, and the second which writes a new title back to the database via the Book model. Notice that the functions are static: this is because, in the case of our book anyways, a notion of $this doesn&#8217;t really make since, as we don&#8217;t actually know what book we want the title for unless we pass the book ID from dojo.</p>
<h2>Writing the RPC Front-end</h2>
<p>Now that we have the backend written, it is fairly quick to write the frontend.</p>
<p>The first step is to create the book rpc file so we can include nickel.rpc.book using a dojo.require statement:</p>
<pre>/html/scripts/nickel/RPC/book.js
[js]dojo.provide(‘nickel.rpc.book’);
dojo.require(‘dojo.rpc.JsonService’);

nickel.rpc.book = new dojo.rpc.JsonService(‘/rpc/smd/class/Nickel_RPC_Book’);
[/js]</pre>
<p>The above code snippet should be saved as book.js and placed in /html/scripts/nickel/rpc. When this file is included, a new JsonService object is created with functions populated from the SMD generated by the RPC controller class. As a result, nickel.rpc.book will now contain three functions: simpleEcho, getTitle and setTitle.</p>
<h2>Using The Front-end.</h2>
<p>Finally, we have the opportunity to see the fruit of our labour. Create an indexController and the accompanying view. In the view, after including dojo.js, create a new script block:</p>
<pre>/application/default/views/index/index.phtml
...
[js]<script type=”text/javascript”>
	dojo.registerModulePath(‘nickel’, ‘/scripts/nickel’);
	dojo.require(‘nickel.rpc.book’);

	dojo.addOnLoad(function(){
		nickel.rpc.book.simpleEcho().addCallback(function(msg){
			alert(msg);		//Alert: Hello World
	});

	nickel.rpc.book.getTitle(1).addCallback(function(title){
		alert(title);	//Alert: title of book with ID 1 in database
	});

	nickel.rpc.book.setTitle(1, ‘Foo’).addCallback(function(result){
		alert(‘success’);	//Sets the title of book with ID 1 to ‘Foo’
	});
});
</script>
...
[/js]</pre>
<p>dojo.registerModulePath adds a module path to the dojo loader. This allows us to include our custom nickel modules easily and on-demand.</p>
<h2>Conclusion</h2>
<p>The Dojo Toolkit and Zend Framework provide a highly structured, maintainable JSON RPC system when used together. This can be used to easily propagate dirty javascript data objects to persistent storage in the backend, as well as expose PHP function calls to javascript to return useful data.</p>
<p>I hope you have enjoyed this tutorial. If you find any typos, mistakes or just wish to leave a message, please add a comment below.</p>
<p>I also encourage you to link to this post if you have found it at all useful in developing your web-application.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/20/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
