<?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>Joey Rivera</title>
	<atom:link href="http://www.joeyrivera.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.joeyrivera.com</link>
	<description>Blogging about PHP, Actionscript, MySQL, and other interests.</description>
	<lastBuildDate>Fri, 02 Dec 2011 03:55:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Automate SVN Export to Site w/ Bash Script</title>
		<link>http://www.joeyrivera.com/2011/automate-svn-export-to-site-w-bash-script/</link>
		<comments>http://www.joeyrivera.com/2011/automate-svn-export-to-site-w-bash-script/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 16:30:19 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[automate]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[export]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=685</guid>
		<description><![CDATA[So at work we are finalizing the setup of a new server environment. The site is in PHP and the code is all in SVN. We were trying to decide what process to use to export the SVN contents to the site and that&#8217;s where I decided to learn how to write a bash script. [...]]]></description>
			<content:encoded><![CDATA[<p>So at work we are finalizing the setup of a new server environment. The site is in PHP and the code is all in SVN. We were trying to decide what process to use to export the SVN contents to the site and that&#8217;s where I decided to learn how to write a bash script. This is my first and with some help from <a title="Jesse Charbneau" href="http://jess.thecharbneaus.com/">Jess</a> we created the following script. The script does the following:</p>
<ul>
<li>Does an info on the remote repo to get the revision number</li>
<li>Checks against local revision number which is stored in a file</li>
<li>If the revision numbers don&#8217;t match, it does a diff on both revisions and creates an list with the files that were changed</li>
<li>It then loops through each file and exports it to the site</li>
<li>Finally it stores the new revision number in the file</li>
</ul>
<div>Feel free to use this and tweak it for your needs. This is our first draft, at this point we&#8217;ll start cleaning it up and adding more functionality but it works. Make sure to add a cron job to run it every so often and enjoy.</div>
<div class="dean_ch" style="white-space: wrap;"><span class="re3">#!/bin/bash</span><br />
<span class="re3"># need to figure out what to <span class="kw1">do</span> on files that need to be deleted</span><br />
<span class="re2">TARGET_DIR=</span><span class="st0">&#8216;/path/to/site&#8217;</span><br />
<span class="re2">REPO=</span><span class="st0">&quot;svn://path.to.svn/repo&quot;</span><br />
<span class="re2">REVISION_FILE=</span><span class="st0">&#8216;.revision&#8217;</span></p>
<p><span class="kw3">echo</span> <span class="st0">&quot;Getting info from remote repo&quot;</span><br />
<span class="re2">REMOTE_VERSION=</span>$<span class="br0">&#40;</span>svn info <span class="re1">$REPO</span> | <span class="kw2">grep</span> Revision<span class="br0">&#41;</span><br />
<span class="re2">REMOTE_VERSION=</span>$<span class="br0">&#123;</span>REMOTE_VERSION: <span class="nu0">-4</span><span class="br0">&#125;</span> <span class="re3"># need to update to not hardcode <span class="nu0">4</span> spaces back</span><br />
<span class="re2">CURRENT_VERSION=</span>$<span class="br0">&#40;</span><span class="kw2">more</span> <span class="re1">$REVISION_FILE</span><span class="br0">&#41;</span></p>
<p><span class="kw3">echo</span> <span class="st0">&quot;Current Revision: $CURRENT_VERSION&quot;</span><br />
<span class="kw3">echo</span> <span class="st0">&quot;Remote Revision: $REMOTE_VERSION&quot;</span></p>
<p><span class="kw1">if</span> <span class="br0">&#91;</span> <span class="st0">&quot;$REMOTE_VERSION&quot;</span> -eq <span class="st0">&quot;$CURRENT_VERSION&quot;</span> <span class="br0">&#93;</span><br />
<span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">echo</span> <span class="st0">&quot;No export needed&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">exit</span> <span class="nu0">0</span><br />
<span class="kw1">fi</span></p>
<p><span class="kw3">echo</span> <span class="st0">&quot;Getting diffs between revisions&quot;</span><br />
<span class="re2">difflines=</span>`svn <span class="kw2">diff</span> &#8211;summarize -r <span class="re1">$CURRENT_VERSION</span>:<span class="re1">$REMOTE_VERSION</span> <span class="re1">$REPO</span> <span class="nu0">2</span>&gt;&amp;amp;<span class="nu0">1</span> | <span class="kw2">awk</span> <span class="st0">&#8216;{print $2}&#8217;</span>`</p>
<p><span class="re2">URL_LENGTH=</span>$<span class="br0">&#123;</span><span class="re3">#REPO<span class="br0">&#125;</span></span></p>
<p><span class="kw1">for</span> i <span class="kw1">in</span> `<span class="kw3">echo</span> <span class="re1">$difflines</span>`; <span class="kw1">do</span><br />
&nbsp; &nbsp;<span class="re2">FILENAME=</span>$<span class="br0">&#123;</span>i:<span class="re1">$URL_LENGTH</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="kw3">echo</span> <span class="st0">&quot;svn export ${i} ${TARGET_DIR}${FILENAME}&quot;</span><br />
&nbsp; &nbsp;svn <span class="kw3">export</span> <span class="re0">$<span class="br0">&#123;</span>i<span class="br0">&#125;</span></span> <span class="re0">$<span class="br0">&#123;</span>TARGET_DIR<span class="br0">&#125;</span></span><span class="re0">$<span class="br0">&#123;</span>FILENAME<span class="br0">&#125;</span></span><br />
<span class="kw1">done</span></p>
<p><span class="kw3">echo</span> <span class="st0">&quot;Saving revision number&quot;</span><br />
<span class="kw3">echo</span> <span class="re0">$<span class="br0">&#123;</span>REMOTE_VERSION<span class="br0">&#125;</span></span> &gt; <span class="re1">$REVISION_FILE</span></div>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2011/automate-svn-export-to-site-w-bash-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend_Json_Server and how to call it via JSON-RPC 2.0</title>
		<link>http://www.joeyrivera.com/2011/zend_json_server-and-how-to-call-it-via-json-rpc-2-0/</link>
		<comments>http://www.joeyrivera.com/2011/zend_json_server-and-how-to-call-it-via-json-rpc-2-0/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 22:32:04 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[2.0]]></category>
		<category><![CDATA[json-rpc]]></category>
		<category><![CDATA[jsonrpc]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[zend_json_server]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=656</guid>
		<description><![CDATA[So I started playing with Zend_Json_Server and was having a hard time trying to figure out how to call the server from a client. Finally I checked the JSON-RPC 2.0 spec and read a very important detail that I had not realized: The Request is expressed as a single JSON Object This was the key [...]]]></description>
			<content:encoded><![CDATA[<p>So I started playing with <a title="Zend_Json_Server docs" href="http://framework.zend.com/manual/en/zend.json.server.html">Zend_Json_Server</a> and was having a hard time trying to figure out how to call the server from a client. Finally I checked the <a title="Json-Rpc 2.0 specs" href="http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal?pli=1#request-procedure-call">JSON-RPC 2.0 spec</a> and read a very important detail that I had not realized:</p>
<blockquote><p>The Request is expressed as a single JSON Object</p></blockquote>
<p>This was the key to my problem. There are 4 parameters that can be sent with each JSON-RPC 2.0 request but I was sending each as a post var which is not what Zend_Json_Server expects. It simply wants one json encoded object with all the parameters inside. The 4 available parameters are:</p>
<ol>
<li>jsonrpc &#8211; the version you are using; I&#8217;m using 2.0.</li>
<li>method &#8211; the name of the method you want to call in the server.</li>
<li>params &#8211; object of parameters your method needs. If you don&#8217;t need any, don&#8217;t send this param.</li>
<li>id &#8211; an identifier (anything you want) that will be sent to and from the server for this request.</li>
</ol>
<p>I&#8217;m using Zend_Http_Client() to make the request and here is an example:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="re0">$params</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;jsonrpc&#8217;</span> =&gt; <span class="st0">&#8217;2.0&#8242;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;method&#8217;</span> =&gt; <span class="st0">&#8216;find&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;params&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8217;326691&#8242;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;id&#8217;</span> =&gt; <span class="st0">&#8216;test&#8217;</span><br />
<span class="br0">&#41;</span>;</p>
<p><span class="re0">$http</span> = <span class="kw2">new</span> Zend_Http_Client<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$http</span>-&gt;<span class="me1">setUri</span><span class="br0">&#40;</span><span class="st0">&#8216;http://localhost/path/to/jsonrpc/server.php&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$http</span>-&gt;<span class="me1">setMethod</span><span class="br0">&#40;</span>Zend_Http_Client::<span class="me2">POST</span><span class="br0">&#41;</span>;<br />
<span class="re0">$http</span>-&gt;<span class="me1">setRawData</span><span class="br0">&#40;</span>json_encode<span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$http</span>-&gt;<span class="me1">request</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">getBody</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
<p><span id="more-656"></span>And here is what I see in my browser when I make the call:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="br0">&#123;</span><br />
-result: <span class="br0">&#123;</span><br />
student_id: <span class="nu0">326691</span><br />
title: <span class="kw2">null</span><br />
first_name: <span class="st0">&quot;Accountbuilder&quot;</span><br />
last_name: <span class="st0">&quot;Random59&quot;</span><br />
middle_initial: <span class="st0">&quot;&quot;</span><br />
suffix: <span class="kw2">null</span><br />
address: <span class="st0">&quot;some place&quot;</span><br />
address2: <span class="kw2">null</span><br />
city: <span class="st0">&quot;Dallas&quot;</span><br />
-state: <span class="br0">&#123;</span><br />
state_id: <span class="nu0">11</span><br />
name: <span class="kw2">null</span><br />
abbr: <span class="kw2">null</span><br />
display_name: <span class="kw2">null</span><br />
sales_tax: <span class="nu0">0</span><br />
<span class="br0">&#125;</span><br />
zip: <span class="st0">&quot;30132&quot;</span><br />
phone: <span class="st0">&quot;111-111-1111&quot;</span><br />
fax: <span class="kw2">null</span><br />
username: <span class="kw2">null</span><br />
password: <span class="kw2">null</span><br />
<span class="br0">&#125;</span><br />
id: <span class="st0">&quot;test&quot;</span><br />
error: <span class="kw2">null</span><br />
jsonrpc: <span class="st0">&quot;2.0&quot;</span><br />
<span class="br0">&#125;</span></div>
<p>Basically, all I had to do was</p>
<ul>
<li>create an array of all the parameters I want to send on my request object. I&#8217;m calling the find method and passing an id</li>
<li>create a new client object</li>
<li>set the url to where your setting up your Zend_Json_Server</li>
<li>set the client to post (Zend_Json_Server only seems to handle post at this time)</li>
<li>json_encode your parameters array</li>
<li>pass the json_encoded object to the setRawData so it passes exactly what we want which is one json object to the server</li>
<li>call request to send the request and finally get body to show the response.</li>
</ul>
<p>Here is my code for the server.php file so you can see how I&#8217;m setting up the server:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="re0">$server</span> = <span class="kw2">new</span> Zend_Json_Server<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$server</span>-&gt;<span class="me1">setClass</span><span class="br0">&#40;</span><span class="st0">&#8216;Student&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$response</span> = <span class="re0">$server</span>-&gt;<span class="me1">handle</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$response</span>;</div>
<p>I setup the server instance, add a class to handle the requests, call handle and echo the response. Student will look for the Student.php class so make sure it&#8217;s available in your include paths. That&#8217;s it, hope you found this helpful. As a side note, I noticed Zend_Amf_Server has a method to addDirectory instead of adding each class separately. Hopefully this gets added to Zend_Json_Server at some point.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2011/zend_json_server-and-how-to-call-it-via-json-rpc-2-0/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Facebook Graph API App Easy w/ PHP SDK</title>
		<link>http://www.joeyrivera.com/2010/facebook-graph-api-app-easy-w-php-sdk/</link>
		<comments>http://www.joeyrivera.com/2010/facebook-graph-api-app-easy-w-php-sdk/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 20:14:56 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=642</guid>
		<description><![CDATA[NOTE: This post was written using Facebook&#8217;s PHP SDK version 2.1.2. Since this post was made, the PHP SDK has changed and some of the process that are explained below may have changed as well. At some point I&#8217;ll have to revisit this post and update it but at this time just keep in mind [...]]]></description>
			<content:encoded><![CDATA[<p>NOTE: This post was written using Facebook&#8217;s PHP SDK version 2.1.2. Since this post was made, the PHP SDK has changed and some of the process that are explained below may have changed as well. At some point I&#8217;ll have to revisit this post and update it but at this time just keep in mind of the above.</p>
<p>As promised, here is a post (similar to my Twitter API post) on using the Facebook API. There are many reason why one would want to access the Facebook API &#8211; maybe to create a mobile app that lets you post photos to your Facebook albums, or maybe you just want to show your last few Facebook status updates on your blog; what ever the reason may be, Facebooks Graph API mixed in with their PHP SDK makes it really easy to accomplish this.</p>
<h2>Objectives</h2>
<ul>
<li>Setup our environment</li>
<li>Register an app on Facebook</li>
<li>Understand the authentication process and extended parameters</li>
<li>Understand Graph API</li>
<li>Retrieve our latest status updates</li>
<li>Add a new status update</li>
<li>Retrieve our photos from our albums</li>
<li>Add a new photo<span id="more-642"></span></li>
</ul>
<h2>Setup our Environment</h2>
<p>You have two options here, you can access my github and download this project with all required files and library or you can follow this tutorial step by step &#8211; it&#8217;s really up to you. If you want to download all the files ahead of time, you can get them at this github <a title="github repo for this project" href="https://github.com/joeyrivera/Facebook-Graph-API-Examples" target="_blank">repo</a>. If you are going step by step, first create a folder (I&#8217;m calling mine facebook) in your server where you want this site, next create a folder named library in the root of this site, and finally add the following two files facebook.php and fb_ca_chain_bundle.crt in the library folder that you can get from the Facebook PHP SDK repo at: <a title="Facebook PHP SDK repo" href="https://github.com/facebook/php-sdk/tree/master/src/" target="_blank">https://github.com/facebook/php-sdk/tree/master/src/</a>.</p>
<h2>Register an App on Facebook</h2>
<p>I&#8217;m making the assumption you already have a facebook account and if you don&#8217;t, first create one. To create an app on Facebook, you first need to confirm your account by giving Facebook a phone number where they can send you a code. This may be a new process since I don&#8217;t remember having to do this a few months ago. Go to <a href="http://developers.facebook.com/setup">http://developers.facebook.com/setup</a> and if your account is not verified, you&#8217;ll be prompted to add the information mentioned above. After verifying your accout, you&#8217;ll be taken to the &#8216;Create an Application&#8217; page.</p>
<div class="wp-caption aligncenter" style="width: 355px"><img title="Create App" src="/blog_files/642/createapp.gif" alt="Create App" width="345" height="369" /><p class="wp-caption-text">This is what the page should look like</p></div>
<p>Simply give your site a name and type in your site&#8217;s url and click create app. In my case I&#8217;m calling my app &#8216;Blog Test&#8217; and my site would be &#8216;http://www.joeyrivera.com/&#8217;. Next you will be prompted to type in a captcha and continue. Now you are done setting up your app, you see a screen like the following with your app id and app secret:</p>
<div class="wp-caption aligncenter" style="width: 338px"><img title="App Created" src="/blog_files/642/appcreated.gif" alt="App Created" width="328" height="113" /><p class="wp-caption-text">Here is your app info</p></div>
<h2>Authenticating and Extended Parameters</h2>
<p>Facebook uses OAuth for authenticating involving tokens being send back and forth but we don&#8217;t have to concern ourselves with the details &#8211; the Facebook PHP SDK does it all for us. It makes sure to send all the required information in the proper format so Facebook gets what it needs and sends us back what we need. You can read more about authenticating with Facebook at their <a title="Facebook Authentication" href="http://developers.facebook.com/docs/authentication/">site</a> and you can also read my <a title="Joey Rivera Twitter API" href="http://www.joeyrivera.com/2010/twitter-api-oauth-authentication-and-zend_oauth-tutorial/">Twitter API post</a> that discusses the OAuth in a little more detail if you are interested. The SDK also takes care of handling all API calls for us so we only have to give it the resource we are trying to access, let it know if we want to do a get or post, and finally give it all the parameters required for the call.</p>
<p>Extended Parameters is an interesting way of restricting access to an app (I&#8217;m using the term app to describe what we are building here) through the API. Unless a user allows access to certain parts of their account, an app will not be able to modify nor read parts of the account even if they are authenticated. Extended Parameters need to be explicitly assigned at the point of authenticating. When the user is taken to Facebook and asked to allow access to their account, the user is also presented with all the various parts of their account this app wants to interact with. Here is an example of what the user will see when trying to authenticate with our app:</p>
<div class="wp-caption aligncenter" style="width: 578px"><a href="All requested permissions"><img title="Extended Permissions" src="/blog_files/642/permissions.gif" alt="" width="568" height="410" /></a><p class="wp-caption-text">Extended Permissions</p></div>
<p>The first one in the screen shot is the default requested permission to access all the users basic information. The other three we need to accomplish our goals set including: read and post status updates as well as view and post photos. <a title="Facebook Extended Permissions" href="http://developers.facebook.com/docs/authentication/permissions">Here</a> you can see a complete list of all the available extended permissions. If you access that link, you&#8217;ll see there are a lot of permissions. I recommend taking some time reading through their descriptions to get a better understanding of the kinds of things you can do with the API. There have been times where I&#8217;ve tried to do something with an app and the Facebook Graph API without success only to find out I hadn&#8217;t requested a required permission for that to work.</p>
<p>Time for code, what we are about to do is to create an array with our app id and app secret to feed to the Facebook class when we instantiate it. Next, we are going to check to see if we are authenticated and if not, redirect us to the Facebook authenticate page passing it the extended parameters we want access to. Below is the code for the config.php file. Download form my <a title="Joey Rivera GitHub Repository" href="https://github.com/joeyrivera/Facebook-Graph-API-Examples">repository</a> or create the file below on the root of your site:</p>
<h4>config.php</h4>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">require_once</span> <span class="st0">&#8216;library/facebook.php&#8217;</span>;</p>
<p><span class="re0">$app_id</span> = <span class="st0">&quot;yourappid&quot;</span>;<br />
<span class="re0">$app_secret</span> = <span class="st0">&quot;yourappsecret&quot;</span>;</p>
<p><span class="re0">$facebook</span> = <span class="kw2">new</span> Facebook<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;appId&#8217;</span> =&gt; <span class="re0">$app_id</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;secret&#8217;</span> =&gt; <span class="re0">$app_secret</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;cookie&#8217;</span> =&gt; <span class="kw2">true</span><br />
<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/is_null"><span class="kw3">is_null</span></a><span class="br0">&#40;</span><span class="re0">$facebook</span>-&gt;<span class="me1">getUser</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/header"><span class="kw3">header</span></a><span class="br0">&#40;</span><span class="st0">&quot;Location:{$facebook-&gt;getLoginUrl(array(&#8216;req_perms&#8217; =&gt; &#8216;user_status,publish_stream,user_photos&#8217;))}&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/exit"><span class="kw3">exit</span></a>;<br />
<span class="br0">&#125;</span></div>
<p>Make sure to update the app_id and app_secret variables with the information you received from Facebook after registering your app. Let me give you a quick explanation of the code. First we include the facebook.php file that we downloaded from the Facebook PHP SDK github repository. Then we instantiate a facebook instance passing it the app id, app secret, and tell it to use cookies to store the session/token information after authenticating. Next we call getUser() to see if we are already authenticated &#8211; null means we are not, else we receive the users id. If we are not authenticated, we redirect the user to Facebook to authenticate. The url is provided to us from the getLoginUrl method. We are sending that method an array with a key req_perms (required permissions) and the value is a comma delimited list of all the extended permissions we want access to. Again, a complete list of all permissions can be found at <a title="Facebook Extended Permissiosn" href="http://developers.facebook.com/docs/authentication/permissions">Facebooks docs</a>.</p>
<p>Go ahead and try to access this page in your browser. You should be immediately redirected to Facebook. If you are not already logged in with your Facebook account, you&#8217;ll first be asked to log in with the user which you want your app to access. Next you&#8217;ll see the &#8216;Request for Permission&#8217; page, click allow and you&#8217;ll be taken back to the config.php page on your server. This process takes you back to the page which initiated the authentication which was the config.php page. We have now successfully authenticated with Facebook.</p>
<p>In testing your app, you may decide you need more or less extended permissions. While you are authenticated with Facebook and have your token stored in a cookie, you won&#8217;t be able to re-authenticate using this code since you&#8217;ll be getting a User object back so you have a few options: You can close your browser, clear cookies, and authenticate again after modifying your code; You can force another echo or header redirect to the getLoginUrl() again with the new parameters; or you can log into your Facebook account (the user you authenticated), click on account on the top right, privacy settings, and in the bottom left you&#8217;ll see application and websites, click on edit your settings. Under applications you use, you should see your app listed, click on edit settings. Finally click on the &#8216;x&#8217; delete button to delete your app from the list. This will now remove your app from this users app list and won&#8217;t allow the app to access this account until the user authenticates again.</p>
<h2>Graph API</h2>
<p>This was confusing to me at first, specially since I keep rushing my project instead of taking my time to carefully look and read over the documents to truly understand what&#8217;s going on. Here is the <a title="Facebook Graph API Overview" href="http://developers.facebook.com/docs/api">Facebook Graph API overview</a> if you would like to read that first but I&#8217;ll try to summarize it here. Graph API allows you to call various resources all of which will be returned to you as JSON objects. You&#8217;ll have to spend some time at the <a title="Facebook Graph API References" href="http://developers.facebook.com/docs/reference/api/">Graph API References</a> page to understand the different objects available, parameters they have, and what the required extended permissions are to access them. I&#8217;ll try to explain connections in a sec.</p>
<p>Lets talk about the <a title="Facebook Graph API User" href="http://developers.facebook.com/docs/reference/api/user">User</a> object first. If you look at the reference page for user, you&#8217;ll see that to call the user object (the user who is authenticated by the app) you would call the graph api url with a &#8216;/me&#8217; at the end. If the call is made successfully, you&#8217;ll receive a JSON object with all the possible properties defined in the reference page (if they are set). Here is a quick example.</p>
<h4>user.php</h4>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">require_once</span> <span class="st0">&#8216;config.php&#8217;</span>;<br />
<span class="re0">$me</span> = <span class="re0">$facebook</span>-&gt;<span class="me1">api</span><span class="br0">&#40;</span><span class="st0">&#8216;/me&#8217;</span><span class="br0">&#41;</span>;<br />
<a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><span class="re0">$me</span><span class="br0">&#41;</span>;</div>
<p>If you run this code you get something like this:</p>
<div class="wp-caption aligncenter" style="width: 596px"><img title="User Object" src="/blog_files/642/user.gif" alt="User Object" width="586" height="379" /><p class="wp-caption-text">This is my user object and properties.</p></div>
<p>Once you have the object, you can access it&#8217;s properties or do what you need with it. Now I&#8217;ll try to explain connections. If you look at the user reference page again and scroll down, you&#8217;ll see a connections section. These are the objects you can get that belong to this user. To access those objects you would call the url /me/object you want. For example, if you want to get this users albums, you would call /me/albums and this would return an array of album objects but remember to meet the required permission. For your app to access /me/albums, you need the user_photos extended permission (which we set in our config.php file).</p>
<p>So a connection is just a bridge between one object an another. Another example would be lets say we do as we did above and get all the users albums. Now we want to see all the photos inside each album. If you look at the <a title="Facebook Graph API Album Object" href="http://developers.facebook.com/docs/reference/api/album">album</a> object, you&#8217;ll notice that under connections is photos which returns an array of photo objects. That is what we would call to get all the photos in that album for each album and you&#8217;ll see the code to do just this later on.</p>
<h2>Get Status Posts</h2>
<p>Create the following page and I&#8217;ll explain the code below.</p>
<h4>status.php</h4>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">require_once</span> <span class="st0">&#8216;config.php&#8217;</span>;</p>
<p><span class="co1">// show statuses</span><br />
<span class="re0">$statuses</span> = <span class="re0">$facebook</span>-&gt;<span class="me1">api</span><span class="br0">&#40;</span><span class="st0">&#8216;/me/statuses&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$statuses</span><span class="br0">&#91;</span><span class="st0">&#8216;data&#8217;</span><span class="br0">&#93;</span> <span class="kw1">as</span> <span class="re0">$status</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$status</span><span class="br0">&#91;</span><span class="st0">&quot;message&quot;</span><span class="br0">&#93;</span>, <span class="st0">&quot;&lt;br /&gt;&quot;</span>;<br />
<span class="br0">&#125;</span></div>
<p>First include the config.php file we created earlier (you&#8217;ll include this in all the other pages as well). The api method is what we&#8217;ll be using every time we need to call a resource and it can take in three parameters: the resource, get/post (defaults to get), and params (if any). In this case we want to call the statuses connection in the <a title="Facebook Graph API User Object" href="http://developers.facebook.com/docs/reference/api/user">user</a> object which returns and array of status messages. After receiving the messages, we loop through each and echo them out. If you want to see all the properties of each status, just do a var_dump on each status. That&#8217;s it, now the next example.</p>
<h2>Add New Status</h2>
<p>Here we are doing something a bit different, we are publishing to Facebook and for more info you can look at the <a title="Facebook Graph API Overview" href="http://developers.facebook.com/docs/api">Facebook Graph API Overview</a> in the publishing section. We want to create a new post so lets look at the <a title="Facebook Graph API Post Object" href="http://developers.facebook.com/docs/reference/api/post">reference guide</a> for information on post and its properties. Scroll down to the publishing section and notice we need the publish_stream extended property and you can see all the different properties that this object supports. I&#8217;m personally a bit confused on what is considered a required property and what it not, is seems nothing is required but for this example we want to submit a post with a message.</p>
<h4>status_add.php</h4>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">require_once</span> <span class="st0">&#8216;config.php&#8217;</span>;</p>
<p><span class="co1">// add a status message</span><br />
<span class="re0">$status</span> = <span class="re0">$facebook</span>-&gt;<span class="me1">api</span><span class="br0">&#40;</span><span class="st0">&#8216;/me/feed&#8217;</span>, <span class="st0">&#8216;POST&#8217;</span>, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;message&#8217;</span> =&gt; <span class="st0">&#8216;This post came from my app.&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><span class="re0">$status</span><span class="br0">&#41;</span>;</div>
<p>This is all the code required to make a post! It&#8217;s that easy. We call the api method, tell it we want to call the /me/feed connection, set method to post, and finally pass an array with the properties we want to set &#8211; in this case just the message property. If you wanted to set other properties, you would have set them in that array such as &#8216;link&#8217; =&gt; &#8216;http://link.to.something&#8217;, etc. If the call is successfully, you&#8217;ll receive an id back which is the id for the new post you just created. Run this code and if all goes well, you should be able to go check our the users Facebook wall and see this latest post. I don&#8217;t think you can post the same message twice (unless I&#8217;m confusing Facebook with Twitter) so if you try it twice and it doesn&#8217;t work, that might be why.</p>
<h2>View Photos From Albums</h2>
<p>In this example, we want to get all the different albums for our user. Then we need to loop through each album and make a second call that will return all the photos for each album.</p>
<h4>photos.php</h4>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">require_once</span> <span class="st0">&#8216;config.php&#8217;</span>;</p>
<p><span class="co1">// get albums</span><br />
<span class="re0">$albums</span> = <span class="re0">$facebook</span>-&gt;<span class="me1">api</span><span class="br0">&#40;</span><span class="st0">&#8216;/me/albums&#8217;</span><span class="br0">&#41;</span>;</p>
<p><span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$albums</span><span class="br0">&#91;</span><span class="st0">&#8216;data&#8217;</span><span class="br0">&#93;</span> <span class="kw1">as</span> <span class="re0">$album</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// get all photos for album</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$photos</span> = <span class="re0">$facebook</span>-&gt;<span class="me1">api</span><span class="br0">&#40;</span><span class="st0">&quot;/{$album['id']}/photos&quot;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$photos</span><span class="br0">&#91;</span><span class="st0">&#8216;data&#8217;</span><span class="br0">&#93;</span> <span class="kw1">as</span> <span class="re0">$photo</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;&lt;img src=&#8217;{$photo['source']}&#8217; /&gt;&quot;</span>, <span class="st0">&quot;&lt;br /&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
<p>Here we call the albums connection on user to get all the album objects. We loop through each and for each album get the album id to then call the <a title="Facebook Graph API Photo Object" href="http://developers.facebook.com/docs/reference/api/photo">photo</a> connection on the <a title="Facebook Graph API Album Object" href="http://developers.facebook.com/docs/reference/api/album">album</a> object. If this sounds confusing just let me know and I&#8217;ll try to explain this further. When I think of connections I think of joins in a db. It&#8217;s like saying I want to join the albums table for the user in the user table therefor retrieving all rows in ablum for a specific user.</p>
<h2>Add Photo</h2>
<p>In the interest of time and complexity, I&#8217;m just going to add a photo without specifying an album. By doing this, Facebook will automatically create a new album to add this photo to. Just know that you can specify an album to add photos directly too if needed.</p>
<h4>photos_add.php</h4>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">require_once</span> <span class="st0">&#8216;config.php&#8217;</span>;</p>
<p><span class="re0">$img</span> = <a href="http://www.php.net/realpath"><span class="kw3">realpath</span></a><span class="br0">&#40;</span><span class="st0">&quot;C:<span class="es0">\\</span>path<span class="es0">\\</span>to<span class="es0">\\</span>file.jpg&quot;</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">// allow uploads</span><br />
<span class="re0">$facebook</span>-&gt;<span class="me1">setFileUploadSupport</span><span class="br0">&#40;</span><span class="st0">&quot;http://&quot;</span> . <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&#8216;SERVER_NAME&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">// add a status message</span><br />
<span class="re0">$photo</span> = <span class="re0">$facebook</span>-&gt;<span class="me1">api</span><span class="br0">&#40;</span><span class="st0">&#8216;/me/photos&#8217;</span>, <span class="st0">&#8216;POST&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;source&#8217;</span> =&gt; <span class="st0">&#8216;@&#8217;</span> . <span class="re0">$img</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;message&#8217;</span> =&gt; <span class="st0">&#8216;This photo came from my app.&#8217;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><br />
<span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><span class="re0">$photo</span><span class="br0">&#41;</span>;</div>
<p>I choose this example for people that want to understand how to post a file through a service like this. First lets start at the top. We need to specify the path to the image we want to upload so change that path to where you file resides. Usually this would be the tmp path for a photo just uploaded to your server via $_FILE. Next we need to tell facebook to allow uploading of a file. I didn&#8217;t investigate that method much other then the comments said to specify the server so I use SERVER_NAME to signify this server. Next we make the call. We are calling /me/photos since that&#8217;s what is specified in the <a title="Facebook Graph API Photos Object" href="http://developers.facebook.com/docs/reference/api/photo">photos reference page</a> under publishing. We are passing two parameters, message is the text that will show up with the image and source is the image we want to upload. Notice there is an @ before the path to the image. This is because we want to post the contents of the file and not pass a string to where the file is. Run this code and if all worked well, you&#8217;ll see this image and an new album in your users Facebook page.</p>
<h2>Conclusion</h2>
<p>If all went well, your users Facebook wall should look something like this:</p>
<div class="wp-caption aligncenter" style="width: 543px"><img title="Done" src="/blog_files/642/done.gif" alt="Done" width="533" height="430" /><p class="wp-caption-text">My test users Facebook wall</p></div>
<p>I hope that with this, you have a good understanding on how Facebook&#8217;s Graph API works. Start trying to call other objects and play with different extended permissions. The Facebook team did a great job in providing us with the PHP SDK to make this so extremely easy so thumbs up to them. If you have any question/comments, just post them below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/facebook-graph-api-app-easy-w-php-sdk/feed/</wfw:commentRss>
		<slash:comments>253</slash:comments>
		</item>
		<item>
		<title>Twitter API, OAuth Authentication, and Zend_Oauth Tutorial</title>
		<link>http://www.joeyrivera.com/2010/twitter-api-oauth-authentication-and-zend_oauth-tutorial/</link>
		<comments>http://www.joeyrivera.com/2010/twitter-api-oauth-authentication-and-zend_oauth-tutorial/#comments</comments>
		<pubDate>Mon, 25 Oct 2010 20:52:03 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[zend_oauth]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=617</guid>
		<description><![CDATA[I recently had to work on a project that required me to interact with the Twitter API. I had done this before so I wasn&#8217;t expecting anything different until I remembered that Twitter had changed their API to start using OAuth for authentication. If you are not familiar with OAuth, it&#8217;s a secure way of [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had to work on a project that required me to interact with the Twitter API. I had done this before so I wasn&#8217;t expecting anything different until I remembered that Twitter had changed their API to start using OAuth for authentication. If you are not familiar with OAuth, it&#8217;s a secure way of authenticating without requiring a user to submit their username and password to third-parties &#8211; you can read more about it at <a title="OAuth Website" href="http://oauth.net/">OAuth</a>. There are lots of resources online that talk about this in detail but I wasn&#8217;t able to find one that explained the entire process in a way that made sense. Hopefully this post will give you everything you need to get started with the Twitter API. I&#8217;m going to go through the steps required to make this work without using the entire zend framework.</p>
<h2>Objective</h2>
<p>This tutorial will go step-by-step in explaining how to create a small PHP application that can interact with the Twitter API. Our goal is to:</p>
<ul>
<li>Authenticate</li>
<li>Display our latest tweets</li>
<li>Post new tweets from PHP</li>
<li>Display the last few times our account was mentioned</li>
</ul>
<p>The only assumptions at this point (other than knowing PHP) is that you have a twitter account and the zend framework library <a title="Get the Zend Framework" href="http://framework.zend.com/download/latest">downloaded</a>. We won&#8217;t be using the entire framework, just some of the files as standalone modules.</p>
<h2>Registering An App</h2>
<p>The first step in being able to communicate with the Twitter API is to register an app in their system so you can receive all the necessary keys to authenticate with OAuth. Go to <a title="Twitter Developer" href="http://dev.twitter.com/">dev.twitter.com</a> and log in with your Twitter account. Now click on &#8216;register an app&#8217; (if that link is not visible then click on &#8216;your apps&#8217; on the top right and then click on &#8216;register an app&#8217; in the next page). These are the values I put in the form on the next page for my app. Feel free to follow along. I&#8217;ll explain the important inputs.</p>
<p><strong>Application:</strong> Joey&#8217;s Blog Example<br />
<strong>Description:</strong> Twitter PHP App<br />
<strong>Application Website:</strong> http://www.joeyrivera.com<br />
<strong>Organization:</strong> None<br />
<strong>Application Type:</strong> Browser<br />
<strong>Callback URL:</strong> http://www.joeyrivera.com/twitter/callback.php<br />
<strong>Default Access Type:</strong> Read &amp; Write<span id="more-617"></span></p>
<p>Most of the above are self-explanatory but let me explain callback since it&#8217;s an important one. Before we can talk to Twitter, we need to authenticate to get a token from Twitter. Once we have our token, we can start calling the API. During authentication, we are actually going to leave our application and go to Twitters website where the user will have to enter their twitter credentials. After the user allows our application and is done authenticating, Twitter will redirect the user back to our applications callback url. We haven&#8217;t created the file yet, but point back to a file called &#8216;callback.php&#8217; where you plan on putting this file. We will create this file later. (I mentioned users don&#8217;t have to give third-parties their user/pass but they still have to let Twitter know it&#8217;s ok for this app to access their account.)</p>
<p>Enter the captcha and register. At this point we have successfully registered our app that can now start communicating with the Twitter API.</p>
<h2>Authenticating</h2>
<p>To authenticate using Zend_Oauth we need to create a consumer object. The consumer needs an array with the following parameters:</p>
<ul>
<li>callbackUrl: Same as the one used during &#8216;registering an app&#8217;.</li>
<li>siteUrl: The url where the token request will take place. In this case: &#8216;http://twitter.com/oauth&#8217;.</li>
<li>consumerKey: This value is assigned to you after registering your app. To get this value, log into dev.twitter.com, go to your apps, and select the app you just created during &#8216;registering an app&#8217; above. All your keys/secret and info will be listed on that page.</li>
<li>consumerSecret: same steps as consumerKey.</li>
</ul>
<p>We are going to be using the code from <a href="http://framework.zend.com/manual/en/zend.oauth.introduction.html">zend docs</a> with a couple minor tweaks or additions. The code is below:</p>
<h4>authenticate.php</h4>
<div class="dean_ch" style="white-space: wrap;"><a href="http://www.php.net/session_start"><span class="kw3">session_start</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/set_include_path"><span class="kw3">set_include_path</span></a><span class="br0">&#40;</span><span class="st0">&#8216;/path/to/zend/library/1.10.8&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">require</span> <span class="st0">&#8216;Zend/Oauth/Consumer.php&#8217;</span>;</p>
<p><span class="re0">$config</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;callbackUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://www.joeyrivera.com/twitter/callback.php&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;siteUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://twitter.com/oauth&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerKey&#8217;</span> =&gt; <span class="st0">&#8216;ASD234ADF34ADSF&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerSecret&#8217;</span> =&gt; <span class="st0">&#8217;24GH789JSDFGDFG345098DF09873SDFSD&#8217;</span><br />
<span class="br0">&#41;</span>;</p>
<p><span class="re0">$consumer</span> = <span class="kw2">new</span> Zend_Oauth_Consumer<span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">// fetch a request token</span><br />
<span class="re0">$token</span> = <span class="re0">$consumer</span>-&gt;<span class="me1">getRequestToken</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">// persist the token to storage</span><br />
<span class="re0">$_SESSION</span><span class="br0">&#91;</span><span class="st0">&#8216;TWITTER_REQUEST_TOKEN&#8217;</span><span class="br0">&#93;</span> = <a href="http://www.php.net/serialize"><span class="kw3">serialize</span></a><span class="br0">&#40;</span><span class="re0">$token</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">// redirect the user</span><br />
<span class="re0">$consumer</span>-&gt;<span class="me1">redirect</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
<p>Create a file and paste the above code in there and save your file as authenticate.php. Go back and modify the values of the $config array to use your callbackUrl, siteUrl, consumerKey, and consumerSecret. Also make sure to modify the include path to include your library folder where the zend framework resides (I&#8217;m using the framework version 1.10.8 for these examples).</p>
<p>Quick explanation of the code. First we start our session since we&#8217;ll be using a session variable to track the request token needed to create the access token later. Then we create a consumer and create the request token. Finally we call redirect on the consumer which sends us to twitter feeding it all the necessary information in the proper format for us to then authenticate. There is lots of magic going on behind the scene and for a better understanding on how the token and signature works read the OAuth docs. I personally find it much easier to use Zend_Oauth instead.</p>
<p>Now lets create the callback file, code is below:</p>
<h4>callback.php</h4>
<div class="dean_ch" style="white-space: wrap;"><a href="http://www.php.net/session_start"><span class="kw3">session_start</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><a href="http://www.php.net/set_include_path"><span class="kw3">set_include_path</span></a><span class="br0">&#40;</span><span class="st0">&#8216;/path/to/zend/library/1.10.8&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">require</span> <span class="st0">&#8216;Zend/Oauth/Consumer.php&#8217;</span>;</p>
<p><span class="re0">$config</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;callbackUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://www.joeyrivera.com/twitter/callback.php&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;siteUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://twitter.com/oauth&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerKey&#8217;</span> =&gt; <span class="st0">&#8216;ASD234ADF34ADSF&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerSecret&#8217;</span> =&gt; <span class="st0">&#8217;24GH789JSDFGDFG345098DF09873SDFSD&#8217;</span><br />
<span class="br0">&#41;</span>;</p>
<p><span class="re0">$consumer</span> = <span class="kw2">new</span> Zend_Oauth_Consumer<span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#41;</span>;</p>
<p><span class="kw1">if</span> <span class="br0">&#40;</span>!<a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#41;</span> &amp;amp;&amp;amp; <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$_SESSION</span><span class="br0">&#91;</span><span class="st0">&#8216;TWITTER_REQUEST_TOKEN&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="re0">$token</span> = <span class="re0">$consumer</span>-&gt;<span class="me1">getAccessToken</span><span class="br0">&#40;</span><span class="re0">$_GET</span>, <a href="http://www.php.net/unserialize"><span class="kw3">unserialize</span></a><span class="br0">&#40;</span><span class="re0">$_SESSION</span><span class="br0">&#91;</span><span class="st0">&#8216;TWITTER_REQUEST_TOKEN&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// Now that we have an Access Token, we can discard the Request Token</span><br />
&nbsp; &nbsp; <span class="re0">$_SESSION</span><span class="br0">&#91;</span><span class="st0">&#8216;TWITTER_REQUEST_TOKEN&#8217;</span><span class="br0">&#93;</span> = <span class="kw2">null</span>;<br />
<span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co1">// Mistaken request? Some malfeasant trying something?</span><br />
&nbsp; &nbsp; <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">&#40;</span><span class="st0">&#8216;Invalid callback request. Oops. Sorry.&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="co1">// save token to file</span><br />
file_put_contents<span class="br0">&#40;</span><span class="st0">&#8216;token.txt&#8217;</span>, <a href="http://www.php.net/serialize"><span class="kw3">serialize</span></a><span class="br0">&#40;</span><span class="re0">$token</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
<p>Save this file as callback.php after modifying the $config variables and library path just like with authenticate.php. We are once again starting our session to be able to capture the &#8216;TWITTER_REQUEST_TOKEN&#8217; created in the previous step. Then we create the consumer again and check to make sure the session is there and that we received query string parameters from Twitter. If everything is as expected, we feed the consumer all the information and ask it for an access token. This is the token we need to track since it&#8217;s the token we need for any call our application makes to the Twitter API. Since we no longer need the request token, we can remove it from the session.</p>
<p>The last step is to save the token somewhere so we can reuse it and not have to authenticate again. Twitter&#8217;s access token does not expire (at least not now). This means, once we authenticate with Twitter, as long as we have our access token stored and accessible to us, our client will not have to authenticate again (assuming Twitter doesn&#8217;t change their mind later and adds an expiration to their tokens). For the purpose of this example, I&#8217;m storing this token in the file system. Another option is to store this value in the database, it&#8217;s really up to you where you want to put it. If you are saving it to the file system, make sure that file is writable by your application.</p>
<p>Both files are created so lets try it out. Go to your browser and access the authenticate.php file. When the page loads, you should be redirected to Twitter and asked to log in (unless you are already logged into Twitter). Enter your twitter account user/pass that you want to access and continue. Next you&#8217;ll be asked if you want to allow this application to access your account. Go ahead and click allow, then you&#8217;ll be taken to your callback.php url. At this point we have authorized, received our access token, and stored it. Now we are done with our first goal and ready for the good stuff.</p>
<h2>Using our Token</h2>
<p>Our next goal was to display our latest tweets so this will be our first example on how to use our token. Technically, this isn&#8217;t the best example as you don&#8217;t need to authenticate with Twitter to display public user tweets but you&#8217;ll still get to see how to make a call to the Twitter API using our token.</p>
<h4>show_tweets.php</h4>
<div class="dean_ch" style="white-space: wrap;"><a href="http://www.php.net/set_include_path"><span class="kw3">set_include_path</span></a><span class="br0">&#40;</span><span class="st0">&#8216;/path/to/zend/library/1.10.8&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">require</span> <span class="st0">&#8216;Zend/Oauth/Consumer.php&#8217;</span>;</p>
<p><span class="re0">$config</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;callbackUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://www.joeyrivera.com/twitter/callback.php&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;siteUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://twitter.com/oauth&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerKey&#8217;</span> =&gt; <span class="st0">&#8216;ASD234ADF34ADSF&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerSecret&#8217;</span> =&gt; <span class="st0">&#8217;24GH789JSDFGDFG345098DF09873SDFSD&#8217;</span><br />
<span class="br0">&#41;</span>;</p>
<p><span class="re0">$token</span> = <a href="http://www.php.net/unserialize"><span class="kw3">unserialize</span></a><span class="br0">&#40;</span><a href="http://www.php.net/file_get_contents"><span class="kw3">file_get_contents</span></a><span class="br0">&#40;</span><span class="st0">&#8216;token.txt&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><span class="re0">$client</span> = <span class="re0">$token</span>-&gt;<span class="me1">getHttpClient</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setUri</span><span class="br0">&#40;</span><span class="st0">&#8216;http://twitter.com/statuses/user_timeline.json&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setMethod</span><span class="br0">&#40;</span>Zend_Http_Client::<span class="me2">GET</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setParameterGet</span><span class="br0">&#40;</span><span class="st0">&#8216;screen_name&#8217;</span>, <span class="st0">&#8216;joeyrivera&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setParameterGet</span><span class="br0">&#40;</span><span class="st0">&#8216;count&#8217;</span>, <span class="st0">&#8217;10&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$response</span> = <span class="re0">$client</span>-&gt;<span class="me1">request</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><span class="re0">$tweets</span> = json_decode<span class="br0">&#40;</span><span class="re0">$response</span>-&gt;<span class="me1">getBody</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$tweets</span> <span class="kw1">as</span> <span class="re0">$tweet</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$tweet</span>-&gt;<span class="me1">text</span>, <span class="st0">&quot;&lt;br&gt;&quot;</span>;<br />
<span class="br0">&#125;</span></div>
<p>Paste the above code into a file called show_tweets.php and edit the configs yet again plus the library. At this point I&#8217;ll stop mentioning to edit the config and library &#8211; just remember to do the same with the next couple examples. First we get our token which we saved to a file during the callback phase. Then we create a client object, tell it what url to call, the method to use and pass two params to let the API know who&#8217;s tweets we want and how many tweets to return. Finally we tell the client to initiate the request and we display it when it comes back.</p>
<p>Where did I get the uri from? from Twitters docs page. Spend some time there learning all the different methods you can call and what the required parameters are. For <a title="User Timeline" href="http://dev.twitter.com/doc/get/statuses/user_timeline">user_timeline</a> (which is what we want to get our latest tweets) we need to call the uri used above. The last part, the .json at the end tells Twitter that we want a JSON encoded response back which is why we need to do a json_decode on the body to view it. You could have used .xml if you wanted an xml back instead. The docs for user_timeline also specify you need to do a get which is why we set it as a method and add the two get parameters. There are more parameters you can set if you like.</p>
<p>This is what I see when I run this page with my screen name:</p>
<pre>Flash, jQuery, and Php - what a pain you have all been to me today but I'm glad all is well again.
Put my car up on autotrader, check it out if you are in the market for a 2005 Subaru WRX STi or know someone who might: http://is.gd/g3tqv
someone owns a image rollover patent? http://arstechnica.com/tech-policy/news/2010/10/patent-troll-takes-over-the-web-can-it-be-stopped.ars
Microsoft has the best commercials! http://holykaw.alltop.com/microsoft-pokes-fun-at-smartphone-users-in-ne
Finally got oAuth working to post to Twitter from PHP.
Accidentally found this very cool video by RefinedData http://refineddata.com/products/refinedtraining/index.php
You guys have recommendations on course authoring tools like articulate/captivate that don't have a player. Just a place to create content?
Cool story on YouTube instant http://www.feross.org/youtube-instant-media-frenzy/ Congrats to Feross on the accomplishment.
After driving a Z06 Corvette, I have become a believer of American muscle. STi was fun but just doesn't compare to a Z06.
Been week since we paid for Adobe developer support license and we are still not closer to solving our problem. Hoping to make progress soon</pre>
<p>Now lets submit a tweet.</p>
<h4>submit_tweet.php</h4>
<div class="dean_ch" style="white-space: wrap;"><a href="http://www.php.net/set_include_path"><span class="kw3">set_include_path</span></a><span class="br0">&#40;</span><span class="st0">&#8216;/path/to/zend/library/1.10.8&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">require</span> <span class="st0">&#8216;Zend/Oauth/Consumer.php&#8217;</span>;</p>
<p><span class="re0">$config</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;callbackUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://www.joeyrivera.com/twitter/callback.php&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;siteUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://twitter.com/oauth&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerKey&#8217;</span> =&gt; <span class="st0">&#8216;ASD234ADF34ADSF&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerSecret&#8217;</span> =&gt; <span class="st0">&#8217;24GH789JSDFGDFG345098DF09873SDFSD&#8217;</span><br />
<span class="br0">&#41;</span>;</p>
<p><span class="re0">$token</span> = <a href="http://www.php.net/unserialize"><span class="kw3">unserialize</span></a><span class="br0">&#40;</span><a href="http://www.php.net/file_get_contents"><span class="kw3">file_get_contents</span></a><span class="br0">&#40;</span><span class="st0">&#8216;token.txt&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><span class="re0">$client</span> = <span class="re0">$token</span>-&gt;<span class="me1">getHttpClient</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setUri</span><span class="br0">&#40;</span><span class="st0">&#8216;http://twitter.com/statuses/update.json&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setMethod</span><span class="br0">&#40;</span>Zend_Http_Client::<span class="me2">POST</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setParameterPost</span><span class="br0">&#40;</span><span class="st0">&#8216;status&#8217;</span>, <span class="st0">&#8216;I hope to get my blog post on Twitter API with Zend_Oauth up in the next day.&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$response</span> = <span class="re0">$client</span>-&gt;<span class="me1">request</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><span class="re0">$data</span> = json_decode<span class="br0">&#40;</span><span class="re0">$response</span>-&gt;<span class="me1">getBody</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
<a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$data</span>-&gt;<span class="me1">text</span>;</div>
<p>The code is very similar. The resource we want to call this time is <a title="Statuses/Update" href="http://dev.twitter.com/doc/post/statuses/update">statuses/update</a>. It requires a post method so we use POST and setParameterPost instead of GET. The one required param is status &#8211; set that to the string you want to tweet and run this page. Now go check your tweeter account and you should have that status show up. Make sure the string you pass is 140 characters or less. Also, twitter won&#8217;t allow you to submit two identical statuses so if you are testing this code and it&#8217;s not working, make sure you are sending a unique string.</p>
<p>Finally we&#8217;ll create one last example that displays the last 5 mentions of our twitter account.</p>
<h4>mentioned_tweet.php</h4>
<div class="dean_ch" style="white-space: wrap;"><a href="http://www.php.net/set_include_path"><span class="kw3">set_include_path</span></a><span class="br0">&#40;</span><span class="st0">&#8216;/path/to/zend/library/1.10.8&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="kw1">require</span> <span class="st0">&#8216;Zend/Oauth/Consumer.php&#8217;</span>;</p>
<p><span class="re0">$config</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">&#8216;callbackUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://www.joeyrivera.com/twitter/callback.php&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;siteUrl&#8217;</span> =&gt; <span class="st0">&#8216;http://twitter.com/oauth&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerKey&#8217;</span> =&gt; <span class="st0">&#8216;ASD234ADF34ADSF&#8217;</span>,<br />
&nbsp; &nbsp; <span class="st0">&#8216;consumerSecret&#8217;</span> =&gt; <span class="st0">&#8217;24GH789JSDFGDFG345098DF09873SDFSD&#8217;</span><br />
<span class="br0">&#41;</span>;</p>
<p><span class="re0">$token</span> = <a href="http://www.php.net/unserialize"><span class="kw3">unserialize</span></a><span class="br0">&#40;</span><a href="http://www.php.net/file_get_contents"><span class="kw3">file_get_contents</span></a><span class="br0">&#40;</span><span class="st0">&#8216;token.txt&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><span class="re0">$client</span> = <span class="re0">$token</span>-&gt;<span class="me1">getHttpClient</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setUri</span><span class="br0">&#40;</span><span class="st0">&#8216;http://twitter.com/statuses/mentions.json&#8217;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setMethod</span><span class="br0">&#40;</span>Zend_Http_Client::<span class="me2">GET</span><span class="br0">&#41;</span>;<br />
<span class="re0">$client</span>-&gt;<span class="me1">setParameterGet</span><span class="br0">&#40;</span><span class="st0">&#8216;count&#8217;</span>, <span class="st0">&#8217;5&#8242;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$response</span> = <span class="re0">$client</span>-&gt;<span class="me1">request</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><span class="re0">$tweets</span> = json_decode<span class="br0">&#40;</span><span class="re0">$response</span>-&gt;<span class="me1">getBody</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p><span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$tweets</span> <span class="kw1">as</span> <span class="re0">$tweet</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$tweet</span>-&gt;<span class="me1">text</span>, <span class="st0">&quot;&lt;br&gt;&quot;</span>;<br />
<span class="br0">&#125;</span></div>
<p>The <a title="Mentions" href="http://dev.twitter.com/doc/get/statuses/mentions">mentions</a> resource uses GET and doesn&#8217;t require any parameter. I&#8217;m passing a count of 5 so you don&#8217;t get too much back. Here is what I see when I run this page:</p>
<pre>heads up! @mosesngone and @joeyrivera consuming Web Services Nov 4th @atlantaphp #atlantaphp http://meetu.ps/3Rbt</pre>
<h2>Conclusion</h2>
<p>Using Zend_Oauth it&#8217;s really easy to authenticate with OAuth and track your token. At that point calling the Twitter API is very simple. I want to thank the guys at Zend for making our lives so much easier with all these great modules. If you have any question feel free to ask. Hopefully you have all found this post very informative and helpful.</p>
<p>EDIT: Here is a similar post on using <a title="Joey Rivera Facebook Graph API and PHP SDK Post" href="http://www.joeyrivera.com/2010/facebook-graph-api-app-easy-w-php-sdk/">Facebooks Graph API with their PHP SDK</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/twitter-api-oauth-authentication-and-zend_oauth-tutorial/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>My car is for sale! 2005 Subaru WRX STi, 51,300 miles for $21,500 &#8211; SOLD!</title>
		<link>http://www.joeyrivera.com/2010/my-car-is-for-sale-2005-subaru-wrx-sti-51300-miles-for-21500/</link>
		<comments>http://www.joeyrivera.com/2010/my-car-is-for-sale-2005-subaru-wrx-sti-51300-miles-for-21500/#comments</comments>
		<pubDate>Fri, 15 Oct 2010 17:15:04 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[My Car]]></category>
		<category><![CDATA[corvette]]></category>
		<category><![CDATA[sti]]></category>
		<category><![CDATA[subaru]]></category>
		<category><![CDATA[z06]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=611</guid>
		<description><![CDATA[Here is the link to autotrader with all the info: My car for sale. It&#8217;s a great car and I had a blast with it but I have bought a replacement, a Z06. The suby has a lot of mods, you can read about them all in my blog under &#8216;my-car&#8216; &#8211; pushed 450whp with [...]]]></description>
			<content:encoded><![CDATA[<p>Here is the link to autotrader with all the info: <a href="http://www.autotrader.com/fyc/vdp.jsp?ct=p&amp;car_id=288193683&amp;dealer_id=65766299&amp;car_year=2005&amp;rdm=1287156137263&amp;lastStartYear=1981&amp;model=IMPWRX&amp;num_records=25&amp;systime=&amp;make2=&amp;highlightFirstMakeModel=&amp;start_year=2005&amp;keywordsfyc=&amp;keywordsrep=&amp;engine=&amp;certified=&amp;body_code=0&amp;fuel=&amp;awsp=false&amp;search_type=both&amp;distance=25&amp;marketZipError=false&amp;search_lang=en&amp;sownerid=65504949&amp;showZipError=y&amp;make=SUB&amp;keywords_display=&amp;color=&amp;page_location=findacar::ispsearchform&amp;min_price=&amp;drive=&amp;default_sort=newsortbyprice_DESC&amp;seller_type=b&amp;max_mileage=&amp;style_flag=1&amp;sort_type=priceDESC&amp;address=30060&amp;advanced=&amp;end_year=2005&amp;doors=&amp;transmission=&amp;max_price=&amp;cardist=0&amp;standard=false">My car for sale</a>. It&#8217;s a great car and I had a blast with it but I have bought a replacement, a Z06. The suby has a lot of mods, you can read about them all in my blog under &#8216;<a href="http://www.joeyrivera.com/category/projects/my-car/">my-car</a>&#8216; &#8211; pushed 450whp with methanol. Contact me here or at autotrader for more questions. Here are some pictures of both:</p>
<p><img class="aligncenter size-full wp-image-441" title="Bofum1smll" src="http://jamesfleishel.files.wordpress.com/2010/09/bofum1smll.jpg?w=600&amp;h=284" alt="" width="600" height="284" /></p>
<p><span id="more-611"></span></p>
<p><img class="aligncenter size-full wp-image-451" title="Z06 3 smll" src="http://jamesfleishel.files.wordpress.com/2010/09/z06-3-smll.jpg?w=600&amp;h=450" alt="" width="600" height="450" /></p>
<p><img class="aligncenter size-full wp-image-449" title="STI 5 smll" src="http://jamesfleishel.files.wordpress.com/2010/09/sti-5-smll.jpg?w=600&amp;h=450" alt="" width="600" height="450" /></p>
<p><img style="-webkit-user-select: none;" src="http://jamesfleishel.files.wordpress.com/2010/09/z062smll.jpg" alt="" /></p>
<p>All the pics were taken by my brother-in-law, James. You can see the full gallery at his blog <a href="http://jamesfleishel.wordpress.com/2010/09/18/out-with-the-old-in-with-the-new/">James Fleishel</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/my-car-is-for-sale-2005-subaru-wrx-sti-51300-miles-for-21500/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to build an Adobe AIR Badge</title>
		<link>http://www.joeyrivera.com/2010/how-to-build-adobe-air-badge/</link>
		<comments>http://www.joeyrivera.com/2010/how-to-build-adobe-air-badge/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 14:52:07 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[badge]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=593</guid>
		<description><![CDATA[NOTE: This article was written with AIR 1.5 in mind. I can&#8217;t say if the following information will work as intended on AIR 2. If you already know how to build you own Adobe AIR badge, you won&#8217;t find much new information here. This post is more to inform users that you can in fact [...]]]></description>
			<content:encoded><![CDATA[<p>NOTE: This article was written with AIR 1.5 in mind. I can&#8217;t say if the following information will work as intended on AIR 2. If you already know how to build you own Adobe AIR badge, you won&#8217;t find much new information here. This post is more to inform users that you can in fact create your own AIR badge if you didn&#8217;t already know. When I first started working with AIR, I learned about the badge but as far as I was concerned, the badge was a black box who&#8217;s functionality was designed to remain mysterious.  The badge I used was the one <a title="Grant Skinner's website" href="http://www.gskinner.com/">Grant Skinner</a> created and you can get more information from <a title="About the Badge" href="http://www.adobe.com/devnet/air/articles/badge_for_air.html">Adobe</a> on how to use it. For a long time this badge worked well but finally the time has come where I need to make it behave a bit differently so I decided to do a bit of research.</p>
<p>After doing a few Google searches, I found a link to Adobe&#8217;s site with all the technical information on how to create your own AIR badge! I was completely surprised that I never even thought about the possibility that I could write my own badge&#8230; not sure what I was thinking. Nothing is more fun that reinventing the wheel right? After looking at the <a title="Adobe AIR 1.5 Badge" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7e15.html">specifications</a>, I realized it wasn&#8217;t too bad and started to plan out a logical flow on how my badge was supposed to work.</p>
<h2>Requirements</h2>
<p>My current badge has the following issue: a user installs my app through the badge, every time after that point that the user comes back to the badge, they have to &#8216;install&#8217; the app again even thought it was already installed. Instead, I want the badge to sense if the application is installed and if so, launch it (I haven&#8217;t spend much time looking into Grants Badger app but I think it&#8217;ll let you do this as well if used correctly&#8230; I think). The logic for the new badge should be:</p>
<ol>
<li>Check if AIR is installed (If not, install)</li>
<li>Check if my app is installed (If not install)</li>
<li>Launch my app</li>
</ol>
<h2>Setup</h2>
<p>I&#8217;ll be using Flash CS3 since that&#8217;s what I have available to me for this tutorial and I am making the assumption you already know how to use Flash, understand ActionScript 3, and have an AIR app to test. Open Flash and create a new AS3 file and save it in some folder. Now attach a class called &#8216;Badge&#8217; to your file that extends MovieClip. Your class should look like the following:</p>
<div class="dean_ch" style="white-space: wrap;">package<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="kw3">MovieClip</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> Badge <span class="kw3">extends</span> <span class="kw3">MovieClip</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> Badge<span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">trace</span><span class="br0">&#40;</span><span class="st0">&#8216;hi&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
<p>I added a trace in the constructor so I can make sure my class is working. When you test your badge you should see &#8216;hi&#8217; in your output window. Now we are ready to continue.<span id="more-593"></span></p>
<h2>air.swf</h2>
<p>Adobe created a file called air.swf that resides on their server at http://airdownload.adobe.com/air/browserapi/air.swf. This file contains all the functionality required to interact with AIR files through your badge. It can check to see if you have air installed on the local machine and install it, it can check to see if an air app is installed on the local machine and install it or launch. It does it all so the first step in creating a badge is to load this file so you can call it&#8217;s methods.</p>
<p>All we need to do is create a Loader instance, add an event listener to alert us when it&#8217;s done loading the air.swf file and call the load method passing in the url as a URLRequest. The code is below with all the required imports:</p>
<div class="dean_ch" style="white-space: wrap;">package<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="kw3">MovieClip</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">events</span>.<span class="me1">Event</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="me1">Loader</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">net</span>.<span class="me1">URLRequest</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> Badge <span class="kw3">extends</span> <span class="kw3">MovieClip</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">var</span> _air:<span class="kw3">Object</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> Badge<span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> loader:Loader = <span class="kw2">new</span> Loader<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loader.<span class="me1">contentLoaderInfo</span>.<span class="me1">addEventListener</span><span class="br0">&#40;</span>Event.<span class="me1">INIT</span>, airSwfLoaded<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loader.<span class="kw3">load</span><span class="br0">&#40;</span><span class="kw2">new</span> URLRequest<span class="br0">&#40;</span><span class="st0">&#8216;http://airdownload.adobe.com/air/browserapi/air.swf&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">function</span> airSwfLoaded<span class="br0">&#40;</span><span class="kw3">e</span>:Event<span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._air = <span class="kw3">e</span>.<span class="kw3">target</span>.<span class="me1">content</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">trace</span><span class="br0">&#40;</span><span class="kw3">this</span>._air.<span class="me1">getStatus</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
<p>Test the above code and in your output you should see one of the following <a title="Different status responses" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7e15.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7c98">status responses</a> (taken from Adobe&#8217;s site):</p>
<table border="1" cellspacing="0" cellpadding="4">
<thead>
<tr>
<th id="d17e28828" width="NaN%" valign="top">String value</th>
<th id="d17e28831" width="NaN%" valign="top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td width="NaN%" valign="top"><samp>&#8220;available&#8221;</samp></td>
<td width="NaN%" valign="top">The runtime can be installed on this computer but currently it is not installed.</td>
</tr>
<tr>
<td width="NaN%" valign="top"><samp>&#8220;unavailable&#8221;</samp></td>
<td width="NaN%" valign="top">The runtime cannot be installed on this computer.</td>
</tr>
<tr>
<td width="NaN%" valign="top"><samp>&#8220;installed&#8221;</samp></td>
<td width="NaN%" valign="top">The runtime is installed on this computer.</td>
</tr>
</tbody>
</table>
<h2>Handling the response</h2>
<p>Now that we have a status, we can tell the badge to handle it in the appropriate manner. The first status we need to handle is &#8216;available&#8217;. This means AIR is not installed on the machine but can be. By default, AIR needs to be installed before installing an AIR app so in this scenario, all we need to call is install on our app and AIR will be installed first automatically. Here is the <strong>tricky part</strong>, we can&#8217;t automatically call install on an AIR app, it is not allowed. <span style="text-decoration: underline;">You can only call install via a user initiated event such as a button click</span>.</p>
<p>If the status is unavailable, then we can&#8217;t do much other than let the user know they can&#8217;t install AIR on their machine. If the status is installed, then the user already has AIR installed and we need to check if they have our app installed. If they do not, we install it and let them launch it. If they do have it installed, we let them launch it. Below is the complete code that does all the above:</p>
<div class="dean_ch" style="white-space: wrap;">package<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="kw3">MovieClip</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">events</span>.<span class="me1">Event</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="me1">Loader</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">events</span>.<span class="me1">MouseEvent</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">net</span>.<span class="me1">URLRequest</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> fl.<span class="me1">controls</span>.<span class="kw3">Button</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> Badge <span class="kw3">extends</span> <span class="kw3">MovieClip</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">var</span> _air:<span class="kw3">Object</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">var</span> _myButton:<span class="kw3">Button</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> const APPID:<span class="kw3">String</span> = <span class="st0">&#8216;YOUAPPID&#8217;</span>; <span class="co1">// replace with your app id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> const PUBID:<span class="kw3">String</span> = <span class="st0">&#8217;123123123123123123123123.1&#8242;</span>; <span class="co1">// replace with your publisher id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> const APPURL:<span class="kw3">String</span> = <span class="st0">&#8216;http://www.yourdomain.com/YOUAIRAPP.air&#8217;</span>; <span class="co1">// replace with your app url</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> const APPRUNTIME:<span class="kw3">String</span> = <span class="st0">&#8217;1.5&#8242;</span>; <span class="co1">// I&#8217;m using 1.5 as a minimum requirement for this example</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> const AIRSWF:<span class="kw3">String</span> = <span class="st0">&#8216;http://airdownload.adobe.com/air/browserapi/air.swf&#8217;</span>; <span class="co1">// adobe&#8217;s file</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> Badge<span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> loader:Loader = <span class="kw2">new</span> Loader<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loader.<span class="me1">contentLoaderInfo</span>.<span class="me1">addEventListener</span><span class="br0">&#40;</span>Event.<span class="me1">INIT</span>, airSwfLoaded<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loader.<span class="kw3">load</span><span class="br0">&#40;</span><span class="kw2">new</span> URLRequest<span class="br0">&#40;</span><span class="kw3">this</span>.<span class="me1">AIRSWF</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._myButton = <span class="kw2">new</span> <span class="kw3">Button</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>.<span class="me1">addChild</span><span class="br0">&#40;</span><span class="kw3">this</span>._myButton<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">function</span> airSwfLoaded<span class="br0">&#40;</span><span class="kw3">e</span>:Event<span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._air = <span class="kw3">e</span>.<span class="kw3">target</span>.<span class="me1">content</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span><span class="kw3">this</span>._air.<span class="me1">getStatus</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;available&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// install app</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>.<span class="me1">installApp</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;unavailable&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// AIR not supported on this system</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;installed&#8217;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// check if app is installed</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>.<span class="me1">checkApp</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">function</span> checkApp<span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._air.<span class="me1">getApplicationVersion</span><span class="br0">&#40;</span><span class="kw3">this</span>.<span class="me1">APPID</span>, <span class="kw3">this</span>.<span class="me1">PUBID</span>, checkAppCallback<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">function</span> checkAppCallback<span class="br0">&#40;</span><span class="kw3">version</span>:<span class="kw3">String</span><span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">version</span> == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="co1">// app is not installed</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._myButton.<span class="me1">label</span> = <span class="st0">&quot;Install&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._myButton.<span class="me1">addEventListener</span><span class="br0">&#40;</span>MouseEvent.<span class="me1">CLICK</span>, installApp<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._myButton.<span class="me1">label</span> = <span class="st0">&quot;Launch&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._myButton.<span class="me1">addEventListener</span><span class="br0">&#40;</span>MouseEvent.<span class="me1">CLICK</span>, launchApp<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">function</span> installApp<span class="br0">&#40;</span><span class="kw3">e</span>:Event = <span class="kw2">null</span><span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._air.<span class="me1">installApplication</span><span class="br0">&#40;</span><span class="kw3">this</span>.<span class="me1">APPURL</span>, <span class="kw3">this</span>.<span class="me1">APPRUNTIME</span>, <span class="kw2">new</span> <span class="kw3">Array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw2">function</span> launchApp<span class="br0">&#40;</span><span class="kw3">e</span>:Event<span class="br0">&#41;</span>:<span class="kw3">void</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">this</span>._air.<span class="me1">launchApplication</span><span class="br0">&#40;</span><span class="kw3">this</span>.<span class="me1">APPID</span>, <span class="kw3">this</span>.<span class="me1">PUBID</span>, <span class="kw2">new</span> <span class="kw3">Array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
<p>I added a button that depending on the status will display the appropriate label and call the corresponding method. If the status is available we know that my app is probably not installed (since AIR is not installed) so I tell my button to call the install app method. The install app method calls the installApplication method from the air.swf file and passes the following 3 paramets: the url of the app you are trying to install, the AIR runtime required for this app, and an array of parameters required for this app if any (make sure to modify those variables to match your needs). When a user clicks on the button, they will be asked to install AIR, install the AIR application, and allowed to start it.</p>
<p>If the status is installed, we call the check app method to see if our app is already installed on the users machine by seeing what version of the app is installed. A null version means that the app is not installed. If installed, our button will launch the application and if not, we call the install app method that I just described above. The launch application method takes in three parameters: the application id, the publisher id and a array of parameters if the application requires it. <span style="text-decoration: underline;">NOTE</span>: Your AIR application MUST have <a title="BrowserInvocation Information from Adobe" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118676a5d46-8000.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7e19">allowBrowserInvocation</a> set to true in it&#8217;s AIR application descriptor xml file for the badge to be able to launch your AIR application.</p>
<h5>Finding your application id</h5>
<p>Simply go to your AIR application&#8217;s folder and open the descriptor xml file. Look for the id node and that&#8217;s the id you want to use.</p>
<h5>Finding your publisher id</h5>
<p>This one was a bit trickier. First you need to install your AIR application on your system. Once installed, go to the folder where your application was installed and inside there will be a META-INF folder. Inside that folder there is a AIR folder with a publisherid file. Open that file and the string inside is your publisher id. For example: c:\program files\myairapp\META-INF\AIR\publisherid</p>
<p>That should do it. At this point you should have a basic working AIR badge. Now you can customize it any ways you like. Hope you all find this helpful! Feel free to leave any questions or comments.</p>
<h2>Resources:</h2>
<p><a title="Adobe Links" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7e15.html">http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7e15.html</a></p>
<p><a title="Adobe Links" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7ff1.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7c9c">http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7ff1.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7c9c</a></p>
<p><a title="Adobe Links" href="http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7ff0.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7cca">http://help.adobe.com/en_US/AIR/1.5/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7ff0.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7cca</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/how-to-build-adobe-air-badge/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What have I been up to recently&#8230;</title>
		<link>http://www.joeyrivera.com/2010/what-have-i-been-up-to-recently/</link>
		<comments>http://www.joeyrivera.com/2010/what-have-i-been-up-to-recently/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 15:32:18 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=585</guid>
		<description><![CDATA[Last month was an action packed month for me. I had a few events going on and lots of work to get done. Atlanta PHP User Group We had a really cool presentation on load testing using JMeter and Xdebug by Brian DeShong. Load testing and profiling are very important to help identify possible bottlenecks [...]]]></description>
			<content:encoded><![CDATA[<p>Last month was an action packed month for me. I had a few events going on and lots of work to get done.</p>
<h2>Atlanta PHP User Group</h2>
<p>We had a really cool <a href="http://atlantaphp.org/archive/242">presentation</a> on load testing using <a href="http://jakarta.apache.org/jmeter/">JMeter</a> and <a href="http://xdebug.org/">Xdebug</a> by <a href="http://www.deshong.net/">Brian DeShong</a>. Load testing and profiling are very important to help identify possible bottlenecks in your application/server before reaching a breaking point. JMeter allows a user to setup different scenarios to run with varying loads (number of users, ramp up time). It&#8217;s pretty fancy with all the options you can do such as submit variables to pages to simulate login ins to an application and tracking sessions. Xdebug lets us analyze logs to see what was going on in your application to easily spot which part of the execution process took the most amount of time. At that point, you can look at your code to see how to improve that particular process.</p>
<p>At work we have an outside firm doing our testing/load testing so it was nice learning about JMeter so eventually we can start doing some of our own load tests for things we need done asap. I currently use Zend Studio&#8217;s profiler to profile my applications so I probably won&#8217;t be using Xdebug any time soon.</p>
<h2>TEK-X</h2>
<p><img class="alignleft" title="TEK-X Conference" src="http://tek.phparch.com/wp-content/themes/tekx/images/header-logo.png" alt="" width="300" height="100" />I asked around our local user group what conference they would recommend if they could only attend one PHP conference and this was the one I heard the most good things about. This was my first time attending a PHP conference and it was WELL worth it. The sessions were great with three tracks daily to choose from. The conference was small enough where you could spend time with the presenters interacting and asking questions. I met a bunch of new people which made the whole experience that much better. There was always something to do during presentations as well as after hours.</p>
<p>This is the web site for <a href="http://tek.phparch.com/">TEX-K</a> if you want more info or want to take a look at the <a href="http://tek.phparch.com/schedule/">schedule</a>. Some of my favorite were the two Flex sessions by <a href="http://caseysoftware.com/blog">Keith Casey</a> since I want to start doing more Flex and the Lost Art of Simplicty by <a href="http://www.joshholmes.com/blog/">Josh Holmes</a> was interesting as well. It was really nice having a bunch of Adobe and Microsoft people there. They were all great and helpful. We had been having some server hiccups at work and the guys at Microsoft were extremely helpful in trying to help us figure things out. We also learned from various people (both the MS and PHP crowd) that we (at work) should start using IIS instead of Apache for Windows. Microsoft has been spending resources in working with the PHP team to make sure things run smoother with PHP on IIS for Windows than before.</p>
<p>Two thumbs up for Microsoft and Adobe for being there and supporting the community (and for the drinks and dinners :p) . I&#8217;ll definitely try to go next year again.</p>
<h2>Flash Builder for PHP</h2>
<p><img class="alignleft" title="Flash Builder" src="http://www.adobe.com/products/flex/images/overview_flashbuildermnemonic.jpg" alt="" width="80" height="80" />I took a one day-8 hour course on using Flash Builder and wow&#8230; I&#8217;m sold. After working on Flash for so many years, Flex is just too amazing to ignore. The class was taught by Adobe certified <a href="http://stallons.com/bio.html">Jeanette Stallons</a> and it was a small class which was great for us since we could get a lot more time for questions and one on one time. She did a great job keeping our attention and was very easy to follow. This was a hands on class so we each had our own computer to work the examples with.</p>
<p>The class started with us learning about the different Adobe applications, the difference between Flash/Flex, and reasoning behind changing the name Flex builder to Flash builder. Then we went through the basics of the IDE and how to setup a project and what the different folders and files are for. Next is when things got fun. We started creating an application that communicates with the database through PHP. We did all the code manually to better appreciate the last lesson which was creating the exact same application in an automated fashion with literally only a few lines of code at most. That was the coolest part of this class, how easy it is to use the wizards (that actually spit out good code!) to be able to just click and drag and have everything working correctly in such a <span style="text-decoration: underline;">short amount of time</span>.</p>
<p>I already <a href="http://www.adobe.com/products/flashbuilder/">downloaded</a> the two month trial from the Adobe&#8217;s site and have been playing around with Flash Builder at work and at home.</p>
<h2>Google AdWords API v13 to v2009</h2>
<p>A few years ago I wrote an application that heavily uses the Google Adwords API. It worked without me touching it for years until recently Google <a href="http://code.google.com/apis/adwords/articles/migrating.html">changed</a> their Adwords API and my app completely stopped working. This was my fault of course since many months ago Google emailed me letting me know this was going to happen but at the time I figured there wouldn&#8217;t be much difference between both versions so I didn&#8217;t pay much attention to it&#8230; boy was I wrong.</p>
<p>The new API v2009 is very different since you call things differently now and many of the old services I was using no longer exist in the new version. I spent some time trying to rework my code to use the new calls but that was not working well for me. It just seemed as if I was wasting time instead of just starting over with a clean rewrite. Fortunately for me, after doing some research, I found that Google had already created a <a href="http://code.google.com/apis/adwords/v2009/docs/clientlibraries.html">client library</a> for PHP that already did all the heavy lifting code to interact with the services. I downloaded the library, ran a couple tests and everything was working perfectly. All I had to do was rewrite the application using the client library and everything is running smoothly again.</p>
<p>Thanks Google! You saved me a lot of time but don&#8217;t change your API again <img src='http://www.joeyrivera.com/blog_new/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<h2>My Birthday</h2>
<p><img class="alignleft" title="Garmin 405 Watch" src="https://static.garmincdn.com/en/products/010-00658-10/g/cf-lg.jpg" alt="" width="300" height="300" />Not much to mention here other than it was my birthday last month as well so had dinners with parents and drinks with friends. I have been running a lot lately so I bought myself a nice new watch with my birthday money: <a href="https://buy.garmin.com/shop/shop.do?pID=11039">Garmin 405</a>. I saw this watch on sale on <a href="http://www.slickdeals.net/">slickdeals.net</a> for under $200 and I couldn&#8217;t resist. I&#8217;ve used it a couple times already and it&#8217;s great. The GPS seems to be working flawlessly for me so far and all the features it brings are neat to play with. My biggest sellers were: GPS to track my distance and pace and the heart rate monitor.</p>
<p><a href="http://www.atlantatrackclub.org/peachtree.htm">Peachtree Road Race</a>, here I come!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/what-have-i-been-up-to-recently/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Two thumbs up for the wifey!</title>
		<link>http://www.joeyrivera.com/2010/two-thumbs-up-for-the-wifey/</link>
		<comments>http://www.joeyrivera.com/2010/two-thumbs-up-for-the-wifey/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 19:11:04 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ashley fleishel]]></category>
		<category><![CDATA[ashley rivera]]></category>
		<category><![CDATA[kroger]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=579</guid>
		<description><![CDATA[So my wife submitted a design for an eco-friendly bag contest for Kroger late last year. There were over 46,000 entries nation wide and she ended up winning second place!!! Great job sweets! Starting next month (April), if you shop at Kroger, you may be able to purchase her bag from your local Kroger store. [...]]]></description>
			<content:encoded><![CDATA[<p>So my wife submitted a design for an <a href="http://www.designareusablebag.com/vote-for-designs/top-10.aspx">eco-friendly bag contest for Kroger</a> late last year. There were over 46,000 entries nation wide and she ended up winning second place!!! Great job sweets!</p>
<p style="text-align: center;">
<p>Starting next month (April), if you shop at Kroger, you may be able to purchase her bag from your local Kroger store. Here is an article that just came out today from a local magazine:</p>
<p><a href="http://www.mdjonline.com/view/full_story/6794712/article-Marietta-graphic-designer-takes-2nd-in-Kroger-s-reusable-bag-competition?instance=home_news_1st_right">http://www.mdjonline.com/view/full_story/6794712/article-Marietta-graphic-designer-takes-2nd-in-Kroger-s-reusable-bag-competition?instance=home_news_1st_right</a></p>
<p>Feel free to visit Ashley&#8217;s blog and let her know she did a great job: <a href="http://ashleycf.wordpress.com/">Ashley&#8217;s Blog</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/two-thumbs-up-for-the-wifey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Dale Carnegie High Impact Presentations Experience/Review</title>
		<link>http://www.joeyrivera.com/2010/dale-carnegie-high-impact-presentations-reivew/</link>
		<comments>http://www.joeyrivera.com/2010/dale-carnegie-high-impact-presentations-reivew/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 18:22:22 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[dale carnegie]]></category>
		<category><![CDATA[presentations]]></category>
		<category><![CDATA[reivew]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=566</guid>
		<description><![CDATA[Wow&#8230; I can&#8217;t stress enough how much improvement I made over the course of two days from taking this program from Dale Carnegie. Before I continue with this post I want to thank Julianne Rivera (Sr. Business Consultant) for encouraging me to take this class. Had it not been for her, my audience would have paid the [...]]]></description>
			<content:encoded><![CDATA[<p>Wow&#8230; I can&#8217;t stress enough how much improvement I made over the course of two days from taking this program from <a title="Dale Carnegie Web Site" href="http://www.dalecarnegie.com/">Dale Carnegie</a>. Before I continue with this post I want to thank <a title="Julianne Rivera's Email" href="mailto:julianne.rivera@dalecarnegie.com">Julianne Rivera</a> (Sr. Business Consultant) for encouraging me to take this class. Had it not been for her, my audience would have paid the price. I also want to thank Ercell Charles and April Farlow for being great coaches throughout this program and doing a fantastic job. This was my first time taking a Dale Carnegie class and it won&#8217;t be my last. <strong>Make sure to watch the before and after videos below to see why</strong>.</p>
<h4>Why did I want to take this class?</h4>
<p>Every time I receive a comment on this blog from my users letting me know that what I wrote helped them in some way, I find it extremely rewarding. I like being able to share my thoughts, knowledge, and experience with others and have decided I want to start presenting to local user groups to further expand my reach. I know my material, but my presentation skills were lacking. I have my first presentation coming up for the <a title="Atlanta PHP User Group" href="http://www.atlantaphp.org/">Atlanta PHP User Group</a> and I want to make sure I don&#8217;t bore my audience. I did a quick dry run to test my presentation and it wasn&#8217;t very energetic&#8230; it was actually pretty dull. So when the opportunity to take a Dale Carnegie class on presentations presented itself, I took it.<span id="more-566"></span></p>
<h4>About the class</h4>
<p>The program was tough, two days from 8am to 5pm Thursday and Friday none-stop plus homework. The class consisted of 8-9 students and two coaches, Ercell Charles and April Farlow. Both coaches were extremely knowledgeable and great to work with. The focus of the class is not what our content is but how to effectively deliver our content to an audience. How to catch our audience&#8217;s attention and keep them interested throughout. How to add energy and use our voice to get points across.</p>
<p>In two days, we each presented probably 8 times, six of which were recorded. We would receive coaching during each presentation and more coaching when we watched our video afterwards. This was probably the biggest eye opener for me, watching myself on video after a presentation and watching the progression I was making with each presentation. The coaches made us do, what at the time felt like wild and crazy things, but when you watched yourself on the tape, you looked perfectly normal, more than that, you looked like a real presenter!</p>
<p>Not only were the coaches valuable but so was everyone else there. Being able to watch these other people present and interact with them was very helpful to the experience. We all helped each other with lots of positive reenforcement and it was nice watching each individual grow with each presentation. The individual who left the biggest impression with me was one who during his first presentation was very quiet and timid. He lacked confidence and you could tell he wasn&#8217;t in his comfort zone. On the second day, during his last presentation, he was a completely different person. You could not have known this man and the man from the day before were the same person. He was so confident, did an excellent job using his voice and gestured and captured his audience for the entire duration of his presentation.</p>
<p>Below are my before and after videos. Don&#8217;t focus on the content, just focus on how I am delivering the content. Focus on my voice inflection (or lack off), look at my hands and posture. You may want to watch the first then the second a couple times to really get the full experience.</p>
<h4>Before and after videos</h4>
<p>Before:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/ENJ6SmCNIPI&amp;hl=en_US&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/ENJ6SmCNIPI&amp;hl=en_US&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>After:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/p5XTW3xxX6U&amp;hl=en_US&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/p5XTW3xxX6U&amp;hl=en_US&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>I&#8217;ve watched these two videos over and over again with a huge smile on my face and excitement to see the after me. I know I can do much better now to keep my audience entertained! And the best part, this is just the starting point. I now have what I need to keep improving.</p>
<p>The toughest part of this program was the end of the last day &#8211; the questions and answers session. Very tough questions were asked to each of us, questions that we didn&#8217;t necessarily want to answer about us as individuals, our company, or our products and service. Some were tough because they dealt with uncomfortable issues, others were in an attempt to incite anger or discomposure. These questions needed to be asked to teach us how to deal with them in a very professional manner. We were taught not to use &#8216;fighting words&#8217; (like Ercell likes to call them) in our response. We were taught how to deal with individuals who try to bring us down by keeping our credibility and sticking to our values.</p>
<p>Overall I give Ercell, April, and Dale Carnegie an A+ for this High Impact Presentation program. It was very rewarding and I encourage any of you who currently give presentations at work or user groups as well as those like me who want to start presenting to look into this program. You will not regret taking it. If you have any questions about this program feel free to contact <a title="Julianne Rivera's Email" href="mailto:julianne.rivera@dalecarnegie.com">Julianne Rivera</a>.</p>
<p>Have you taken this program before? If so, I&#8217;d like to hear how it went.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/dale-carnegie-high-impact-presentations-reivew/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Using Zend_Paginator with Twitter API and Zend_Cache</title>
		<link>http://www.joeyrivera.com/2010/using-zend_paginator-with-twitter-api-and-zend_cache/</link>
		<comments>http://www.joeyrivera.com/2010/using-zend_paginator-with-twitter-api-and-zend_cache/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 19:15:08 +0000</pubDate>
		<dc:creator>Joey</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[twitter api]]></category>
		<category><![CDATA[twitter services]]></category>
		<category><![CDATA[zend_cache]]></category>
		<category><![CDATA[zend_paginator]]></category>
		<category><![CDATA[zend_rest_client]]></category>

		<guid isPermaLink="false">http://www.joeyrivera.com/?p=545</guid>
		<description><![CDATA[Zend Framework 1.10.0 is out and a comment was posted on my blog that lead me to creating this new post. I&#8217;m going to focus more on Zend_Paginator and Zend_Rest_Client to access Twitters API since I&#8217;ve already created a post on Zend_Cache. Normally, I would use Zend_Service_Twitter to access the twitter service but it still [...]]]></description>
			<content:encoded><![CDATA[<p>Zend Framework 1.10.0 is out and a comment was posted on my blog that lead me to creating this new post. I&#8217;m going to focus more on Zend_Paginator and Zend_Rest_Client to access Twitters API since I&#8217;ve already created a post on <a title="Caching using Zend_Cache" href="http://www.joeyrivera.com/2009/caching-using-phpzend_cache-and-mysql/">Zend_Cache</a>. Normally, I would use <a title="Zend Framework Zend_Service_Twitter" href="http://framework.zend.com/manual/en/zend.service.twitter.html">Zend_Service_Twitter</a> to access the twitter service but it still seems to require authentication to retrieve a users timeline where <a title="Twitter API" href="http://apiwiki.twitter.com/Twitter-REST-API-Method:-statuses-user_timeline?SearchFor=statuses&amp;sp=2">only protected users</a> should require authentication.</p>
<h4>Zend_Paginator</h4>
<p>Zend_Paginator from the Zend Framework site:</p>
<blockquote><p>Zend_Paginator is a flexible component for paginating collections of data and presenting that data to users.</p></blockquote>
<p>Zend_Paginator automatically creates pagination for you by setting up a few parameters and passing it an array of data. What is pagination, if you have ever gone to <a title="Google Search Joey Rivera" href="http://www.google.com/search?rlz=1C1GGLS_enUS291US304&amp;sourceid=chrome&amp;ie=UTF-8&amp;q=joey+rivera">Google</a> and searched for anything, usually you&#8217;ll see something like the following at the bottom of the search results page:</p>
<p style="text-align: center;"><img class="alignnone" title="Google Pagination Example" src="http://farm3.static.flickr.com/2759/4310975845_292c7ffca0_o.gif" alt="" width="267" height="61" /></p>
<p>See the numbers and the text links, this is called pagination. So much data exists for the particular search that it wouldn&#8217;t make sense to display it all in one page. It would cause large amounts of scrolling down to view, the load time of the page would be affected, so we rather show fewer results and give our users the option of viewing more by clicking on the pagination links.</p>
<p>To demonstrate how to use Zend_Paginator I created a sample Zend Framework 1.10.0 application. This application grabs my last 50 tweets using the Twitter API and displays them 10 at a time using Zend_Paginator. I use Zend_Cache to cache my twitter data so I don&#8217;t have to spend time accessing their api every time &#8211; I&#8217;m sure they would appreciate it.</p>
<h4>Bootstrap</h4>
<p>The first step was to create a new zend framework project. I&#8217;m making the assumption that if you are reading this then you already know how to do this. After creating my new project, I added two methods to my bootstrap file to autoload and to init Zend_Cache. My bootstrap looks like the following:<br />
<span id="more-545"></span></p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw2">class</span> Bootstrap <span class="kw2">extends</span> Zend_Application_Bootstrap_Bootstrap<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; protected <span class="kw2">function</span> _initAutoload<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$autoloader</span> = <span class="kw2">new</span> Zend_Application_Module_Autoloader<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;namespace&#8217;</span> =&gt; <span class="st0">&#8216;My&#8217;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;basePath&#8217;</span> &nbsp;=&gt; APPLICATION_PATH,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; protected <span class="kw2">function</span> _initCache<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$front</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;lifetime&#8217;</span> =&gt; <span class="nu0">10</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;automatic_serialization&#8217;</span> =&gt; <span class="kw2">true</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$back</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;cache_dir&#8217;</span> =&gt; APPLICATION_PATH . <span class="st0">&#8216;/../cache&#8217;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$cache</span> = Zend_Cache::<span class="me2">factory</span><span class="br0">&#40;</span><span class="st0">&#8216;Core&#8217;</span>, <span class="st0">&#8216;File&#8217;</span>, <span class="re0">$front</span>, <span class="re0">$back</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Zend_Registry::<span class="me2">set</span><span class="br0">&#40;</span><span class="st0">&#8216;cache&#8217;</span>, <span class="re0">$cache</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
<p>For caching to work correctly, I had to create the &#8216;cache&#8217; folder in my site root. Notice I set a cache lifetime in my bootstrap, I&#8217;ll be overriding it later for my twitter service. I like to set a general lifetime when caching and override the items that I believe need a different lifetime value.</p>
<h4>Twitter Service</h4>
<p>Next was creating my twitter service. I added a folder &#8216;service&#8217; under &#8216;application&#8217; and created a file called &#8216;Twitter.php&#8217;. Here is the content for that file:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw2">class</span> My_Service_Twitter<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; const CACHELIFETIME = <span class="nu0">3600</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; protected <span class="re0">$_screen_name</span> = <span class="kw2">null</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; protected <span class="re0">$_cache</span> = <span class="kw2">null</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="re0">$screen_name</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_screen_name = <span class="re0">$screen_name</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_cache = Zend_Registry::<span class="me2">get</span><span class="br0">&#40;</span><span class="st0">&#8216;cache&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> getUserTimeline<span class="br0">&#40;</span><span class="re0">$count</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&#8216;twitter_&#8217;</span> . <span class="re0">$this</span>-&gt;_screen_name . <span class="re0">$count</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!<span class="br0">&#40;</span><span class="re0">$data</span> = <span class="re0">$this</span>-&gt;_cache-&gt;<span class="me1">load</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$client</span> = <span class="kw2">new</span> Zend_Rest_Client<span class="br0">&#40;</span><span class="st0">&#8216;http://twitter.com/statuses/user_timeline.xml&#8217;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// setup params for service call</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$client</span>-&gt;<span class="me1">screen_name</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;_screen_name<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$client</span>-&gt;<span class="me1">count</span><span class="br0">&#40;</span><span class="re0">$count</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// call service and get all data</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$raw_data</span> = <span class="re0">$client</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// create array with the data we want &#8211; text is the actual tweet 140 chars</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!<a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$raw_data</span>-&gt;<span class="me1">error</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$raw_data</span>-&gt;<span class="me1">status</span> <span class="kw1">as</span> <span class="re0">$tweet</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;text&#8217;</span><span class="br0">&#93;</span> = <span class="br0">&#40;</span>string<span class="br0">&#41;</span><span class="re0">$tweet</span>-&gt;<span class="me1">text</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// save array to cache &#8211; override cache lifetime</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_cache-&gt;<span class="me1">save</span><span class="br0">&#40;</span><span class="re0">$data</span>, <span class="re0">$cache_id</span>, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;twitter&#8217;</span><span class="br0">&#41;</span>, self::<span class="me2">CACHELIFETIME</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
<p>Let me explain what I&#8217;m doing here. First I setup some variables. I setup the cache lifetime var to an hour since I don&#8217;t want to be hitting twitter to often and I don&#8217;t tweet more than a couple times a day anyways. In the construct, I simply set my class properties. Twitter API has various service calls you can make. For the purpose of this app, I simply want to return the last 50 tweets posted by a public user &#8211; me. If you look at the twitter docs, you&#8217;ll see <a title="Twitter Statuses User Timeline Method" href="http://apiwiki.twitter.com/Twitter-REST-API-Method:-statuses-user_timeline?SearchFor=statuses&amp;sp=2">statuses user_timeline</a> will give us just that. The call to the service is very simple. We create a Zend_Rest_Client instance to the service url: http://twitter.com/statuses/user_timeline.xml. Then we setup both parameters (check the link to the twitter api to see the rest of the available params) screen name (the twitter account you are looking for) and count (how many tweets to get back) and call $client-&gt;get(). When I get the raw data from twitter, I create an array storing only the data I need which is text (the actual content of your tweets 140 characters).</p>
<p>Easy enough? I thought so. You&#8217;ll also notice that this functionality is wrapped with caching code. Before calling the service, I check to see if this information is already cached and valid. If so, I just return the cached array else I call the service and store the array in cache. More info my <a title="Caching using PHP/Zend_Cache and MySQL" href="http://www.joeyrivera.com/2009/caching-using-phpzend_cache-and-mysql/">Zend_Cache</a> post on how Zend_Cache works.</p>
<h4>IndexController</h4>
<p>Next I added the following call to my IndexController:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw2">public</span> <span class="kw2">function</span> indexAction<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co1">// needed vars</span><br />
&nbsp; &nbsp; <span class="re0">$screen_name</span> = <span class="st0">&#8216;joeyrivera&#8217;</span>;<br />
&nbsp; &nbsp; <span class="re0">$total_tweets</span> = <span class="nu0">50</span>;<br />
&nbsp; &nbsp; <span class="re0">$tweets_per_page</span> = &nbsp;<span class="nu0">10</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// get tweets</span><br />
&nbsp; &nbsp; <span class="re0">$service</span> = <span class="kw2">new</span> My_Service_Twitter<span class="br0">&#40;</span><span class="re0">$screen_name</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$service</span>-&gt;<span class="me1">getUserTimeline</span><span class="br0">&#40;</span><span class="re0">$total_tweets</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// init paginator</span><br />
&nbsp; &nbsp; <span class="re0">$paginator</span> = Zend_Paginator::<span class="me2">factory</span><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="re0">$paginator</span>-&gt;<span class="me1">setItemCountPerPage</span><span class="br0">&#40;</span><span class="re0">$tweets_per_page</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt;<span class="me1">setCurrentPageNumber</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;_getParam<span class="br0">&#40;</span><span class="st0">&#8216;page&#8217;</span>, <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// send paginator to view</span><br />
&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">view</span>-&gt;<span class="me1">paginator</span> = <span class="re0">$paginator</span>;<br />
<span class="br0">&#125;</span></div>
<p>I started by setting up required params. Then initializing My_Service_Twitter and calling the getUserTimeline method.$data gets all 50 tweets from Twitter through Zend_Rest_Client or loaded straight from the cache. Last few steps are calling Zend_Paginator::factory and passing in the $data array of tweets. The next line sets the number of items we want displayed per page and sets the current page number &#8211; the page querystring variable (<a title="Zend_Paginator Config" href="http://framework.zend.com/manual/en/zend.paginator.configuration.html">more options here</a>). This last part will make sense soon when I show you the pagination.phtml (the actual pagination controls) file that renders the page numbers and previous/next links in the view. Since we are done with our paginator var, we pass it to our view to display.</p>
<h4>Index View</h4>
<p>The view is pretty simple, all it does is display the list of tweets, 10 tweets per page. It also needs to display the pagination controls which is the file I mentioned earlier. Here is the index.phtml file:</p>
<div class="dean_ch" style="white-space: wrap;">&lt; ?php <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">paginator</span><span class="br0">&#41;</span><span class="br0">&#41;</span>: <span class="kw2">?&gt;</span><br />
&lt;ul&gt;<br />
&lt; ?php <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">paginator</span> <span class="kw1">as</span> <span class="re0">$item</span><span class="br0">&#41;</span>: <span class="kw2">?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;li&gt;&lt; ?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$item</span><span class="br0">&#91;</span><span class="st0">&#8216;text&#8217;</span><span class="br0">&#93;</span>; ?&gt;&lt;/li&gt;<br />
&lt; ?php <span class="kw1">endforeach</span>; ?&gt;&lt;/ul&gt;<br />
&lt; ?php <span class="kw1">endif</span>; <span class="kw2">?&gt;</span></p>
<p>&lt; ?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$this</span>-&gt;<span class="me1">paginationControl</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">paginator</span>, <span class="st0">&#8216;Sliding&#8217;</span>, <span class="st0">&#8216;pagination.phtml&#8217;</span><span class="br0">&#41;</span>; <span class="kw2">?&gt;</span></div>
<p>If any items are found, the loop takes place and the items are displayed in the list. Zend_Paginator takes care of handling how many items to show and for what page using that parameters we setup earlier. The last line is important. There are different styles you can use when displaying your pagination such as &#8216;sliding&#8217;, &#8216;jumping&#8217;, &#8216;elastic&#8217; and more. You can read about them all in the <a href="http://framework.zend.com/manual/en/zend.paginator.usage.html">zend docs</a>. &#8216;pagination.phtml&#8217; is the file used to display the page numbers and next/previous links. This file can be made so it&#8217;s reusable across your application and you can customize it anyway you like.</p>
<h4>Pagination.phtml</h4>
<p>Here is my file which is located in my views/scripts/ folder:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">pageCount</span> == <span class="nu0">1</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="co1">// previous</span><br />
<span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">previous</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216;&lt;a href=&quot;&#8217;</span>.<span class="re0">$this</span>-&gt;<span class="me1">url</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;page&#8217;</span> =&gt; <span class="re0">$this</span>-&gt;<span class="me1">previous</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="st0">&#8216;&quot;&gt;&lt; Previous&lt;/a&gt; &#8216;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="kw1">else</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216;&lt; Previous &#8216;</span>; <span class="br0">&#125;</span> <span class="co1">// pages foreach($this-&gt;pagesInRange as $page)</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$page</span> != <span class="re0">$this</span>-&gt;<span class="me1">current</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216; &lt;a href=&quot;&#8217;</span>.<span class="re0">$this</span>-&gt;<span class="me1">url</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;page&#8217;</span> =&gt; <span class="re0">$page</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="st0">&#8216;&quot;&gt;&#8217;</span>.<span class="re0">$page</span>.<span class="st0">&#8216;&lt;/a&gt; &#8216;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216; &#8216;</span>, <span class="re0">$page</span>, <span class="st0">&#8216; &#8216;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="co1">// next</span><br />
<span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">next</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216; &lt;a href=&quot;&#8217;</span>.<span class="re0">$this</span>-&gt;<span class="me1">url</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;page&#8217;</span> =&gt; <span class="re0">$this</span>-&gt;<span class="me1">next</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="st0">&#8216;&quot;&gt;Next &gt;&lt;/a&gt;&#8217;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="kw1">else</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&#8216; Next &gt;&#8217;</span>;<br />
<span class="br0">&#125;</span></div>
<p>If there is only 1 page, do nothing else display the page numbers and if there is a previous or next page, display those links as well. Notice I&#8217;m setting a page variable to add to my querystring. This is so Zend_Paginator knows what page I&#8217;m currently at and can display the correct items. For example: &#8216;www.myapp.com/index/index/&#8217; would default to page one. &#8216;www.myapp.com/index/index/page/3&#8242; would let paginator know we want to display the items that belong to page 3. It also lets the pagination.phtml file know if there is a page 2 and/or 4 to display a back and previous link.</p>
<p style="text-align: left;">Here is a image of the end result:<br />
<img class="aligncenter" src="http://farm5.static.flickr.com/4051/4311491187_79fd88ec56_o.gif" alt="" width="549" height="168" /></p>
<h4>Final Thoughts</h4>
<p>That&#8217;s pretty much it. Hopefully I&#8217;m not forgetting anything. Notice I don&#8217;t have any filtering/validating anywhere. I just wrote this quickly to give a basic understanding on how to use these modules together. I think I&#8217;m going to update my &#8216;Interesting Images&#8217; and &#8216;Interesting Links&#8217; widgets on my sidebar to use pagination and allow users to view older entries.</p>
<p>Something to keep in mind for optimization purposes. Depending on where you are getting your data and how much data you want, it makes more sense to get a total number of items to get an idea of how many pages you need (not get all the data at once!). Then for each page you can get the data that needs to be displayed. For example, I would never call twitter and say: bring back my last one thousand tweets just so I can display 10 on a page and one hundred page numbers. That would be an extreme waste of resources. Instead, I could ask Twitter: how many tweets do I have in total which is all I need to draw my pagination. Then for each page, I can download the data I need and display.</p>
<p>Feel free to leave any questions or comments!</p>
<p>EDIT: Created new post on <a title="Twitter API and OAuth" href="http://www.joeyrivera.com/2010/twitter-api-oauth-authentication-and-zend_oauth-tutorial/" target="_self">using Twitter API and OAuth</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joeyrivera.com/2010/using-zend_paginator-with-twitter-api-and-zend_cache/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

