<?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/"
	>

<channel>
	<title>Cut from the North</title>
	<atom:link href="http://cutfromthenorth.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://cutfromthenorth.com</link>
	<description>Internet Engineering and Product Development</description>
	<pubDate>Thu, 10 Sep 2009 12:55:33 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Handling &#8220;Session key invalid or no longer valid&#8221; errors from Facebook</title>
		<link>http://cutfromthenorth.com/handling-session-key-invalid-or-no-longer-valid-errors-from-facebook/</link>
		<comments>http://cutfromthenorth.com/handling-session-key-invalid-or-no-longer-valid-errors-from-facebook/#comments</comments>
		<pubDate>Thu, 10 Sep 2009 12:55:33 +0000</pubDate>
		<dc:creator>kettle</dc:creator>
		
		<category><![CDATA[server-side]]></category>

		<category><![CDATA[api]]></category>

		<category><![CDATA[cakePHP]]></category>

		<category><![CDATA[Facebook Connect]]></category>

		<guid isPermaLink="false">http://cutfromthenorth.com/?p=134</guid>
		<description><![CDATA[




I&#8217;m not sure if it&#8217;s supposed to work this way, but Facebook&#8217;s PHP client library method get_loggedin_user() doesn&#8217;t do the best job of keeping track of valid sessions.  I seem to recall that even their demo FB Connect application experienced this error&#8230; It&#8217;s easy to reproduce on many FB Connect sites; log into a [...]]]></description>
			<content:encoded><![CDATA[<!-- AdSense Now! V1.77 -->
<!-- Post[count: 2] -->
<div class="adsense adsense-leadin" style="float:right;margin: 12px;"><script type="text/javascript"><!--
google_ad_client = "pub-9136041889207674";
/* 200x200, created 9/10/09 */
google_ad_slot = "1784645762";
google_ad_width = 200;
google_ad_height = 200;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><p>I&#8217;m not sure if it&#8217;s supposed to work this way, but Facebook&#8217;s PHP client library method <code>get_loggedin_user()</code> doesn&#8217;t do the best job of keeping track of valid sessions.  I seem to recall that even their demo FB Connect application experienced this error&#8230; It&#8217;s easy to reproduce on many FB Connect sites; log into a FB Connect site, then go to Facebook, logout of Facebook, and return to your FB Connect site.  Reload the page and you&#8217;ll likely see a <code>Session key invalid or no longer valid</code> error followed by a trace.</p>
<p>So simple solution would be to catch the error; problem is that I don&#8217;t think it&#8217;s terribly obvious how to properly release the session if an error is caught&#8230;  Using CakePHP, I added the following to my beforeFilter method:</p>
<pre class="brush: php;">
if($this-&gt;facebook-&gt;get_loggedin_user()):
    try {
        $this-&gt;user = $this-&gt;facebook-&gt;api_client-&gt;fql_query('SELECT uid, pic_square, first_name FROM user WHERE uid = ' . $this-&gt;facebook-&gt;get_loggedin_user());
    } catch (Exception $ex) {
        $this-&gt;facebook-&gt;clear_cookie_state();
    }
endif;
</pre>
<p>So the only way to reliably test whether or not you have a valid session (since <code>get_loggedin_user()</code> can&#8217;t be trusted) is to run a method that requires one, and see if it throws an error.  Sure, it adds overhead which is why I&#8217;d recommend a light FQL query which will return data I need anyway, but it&#8217;s much better than throwing fatal errors.</p>
<p>If an error is found, <code>clear_cookie_state()</code> seems to effectively destroy the session, and <code>get_loggedin_user()</code> will properly return false in all subsequent code.</p>
]]></content:encoded>
			<wfw:commentRss>http://cutfromthenorth.com/handling-session-key-invalid-or-no-longer-valid-errors-from-facebook/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Twitter&#8217;s API returning HTML instead of XML / JSON</title>
		<link>http://cutfromthenorth.com/twitters-api-returning-html-instead-of-xml-json/</link>
		<comments>http://cutfromthenorth.com/twitters-api-returning-html-instead-of-xml-json/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 21:38:12 +0000</pubDate>
		<dc:creator>kettle</dc:creator>
		
		<category><![CDATA[server-side]]></category>

		<category><![CDATA[api]]></category>

		<category><![CDATA[cakePHP]]></category>

		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://cutfromthenorth.com/?p=151</guid>
		<description><![CDATA[




I wasn&#8217;t going to write about this, but it&#8217;s been two weeks now, and more than a few people are agonizing over their Twitter API based apps not working.  In case the title didn&#8217;t give it away, Twitter has been intermittently returning an empty HTML page as a response to API calls.  I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>I wasn&#8217;t going to write about this, but it&#8217;s been two weeks now, and more than a few people are agonizing over their Twitter API based apps not working.  In case the title didn&#8217;t give it away, Twitter has been intermittently returning an empty HTML page as a response to API calls.  I&#8217;m making XML requests, but the issue is also plaguing JSON requests.  More about it <a href="http://code.google.com/p/twitter-api/issues/detail?id=968" target="_blank">here</a>&#8230;</p>
<p>In an ideal world, a RESTful response should always be in the format requested.  From what I&#8217;ve read, it appears this issue may be caused by recent measures to help prevent DoS attacks.  Either way, I couldn&#8217;t wait any longer for Twitter to address the issue.  Hopefully this helps someone else out&#8230; </p>
<p>My issues began when I first started building an application based on the <a href="http://bakery.cakephp.org/articles/view/twitter-datasource" target="_blank">twitter datasource</a>.  My Twitter data iterators kept throwing errors.  By debugging the response before letting the datasource convert it into an array, I saw the request was retuning a 200 success header, and the following HTML:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &quot;http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd&quot;&gt;
&lt;!-- &lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;
&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; --&gt;
&lt;HTML&gt;
&lt;HEAD&gt;
&lt;META HTTP-EQUIV=&quot;Refresh&quot; CONTENT=&quot;0.1&quot;&gt;
&lt;META HTTP-EQUIV=&quot;Pragma&quot; CONTENT=&quot;no-cache&quot;&gt;
&lt;META HTTP-EQUIV=&quot;Expires&quot; CONTENT=&quot;-1&quot;&gt;
&lt;TITLE&gt;&lt;/TITLE&gt;
&lt;/HEAD&gt;
&lt;BODY&gt;&lt;P&gt;&lt;/BODY&gt;
&lt;/HTML&gt;
</pre>
<p>Based on other user&#8217;s experience, it seemed waiting about .3 of a second usually cleared up the HTML response issue, and within 2-3 additional requests, you retrieved the data you were after.  So I modified my <code>_twitterReqest</code> method, a simple wrapper for my calls to the datasource, to make the same request up to 5 times with a .3 second pause between requests until the data was returned in an acceptable format.</p>
<p>If 5 times wasn&#8217;t enough, I output a message explaining to the user that the API is unresponsive at the moment.  So far, this message has yet to appear, and looking at my logs, I&#8217;ve never had to retry a request more than 2 times.</p>
<p>As soon as I get the data I want, I cache it for 24 hours, hopefully avoiding further issues for another day.</p>
<p>Here&#8217;s a quick look at my method:</p>
<pre class="brush: php;">
function _twitterRequest($method = null, $params = null, $tries = 5, $delay = 300000){
    /*
     * This wrapper method is necessary b/c of issue documented here:
     * http://code.google.com/p/twitter-api/issues/detail?id=968
     * http://code.google.com/p/twitter-api/issues/detail?id=1014
     *
     * iterates through api calls with a .3 second delay to allow twitter responses to clear
     * has yet to fail
     */
    if($method):
        $try = 1;
        while($try &lt;= $tries){
            $response = $this-&gt;Twitter-&gt;$method($params);
            if(isset($response['Hash']['error']) || isset($response['User']) || isset($response['Users'])){
                return $response;
            } else {
                $this-&gt;log($method . ': retry # ' . $try);
                usleep($delay);
                $try ++;
            }
        }
        return false;
    endif;
}
</pre>
<p>It&#8217;s frustrating to have to test against 1 + 1 equaling 2, but I guess it&#8217;s just the price of developing with 3rd party platforms&#8230; The moral here is always check your data against the data format you&#8217;re expecting.  Don&#8217;t assume anything!</p>
]]></content:encoded>
			<wfw:commentRss>http://cutfromthenorth.com/twitters-api-returning-html-instead-of-xml-json/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Trim down Twitter API responses with CakePHP&#8217;s Set::extract</title>
		<link>http://cutfromthenorth.com/trim-down-twitter-api-responses-with-cakephps-set-extract/</link>
		<comments>http://cutfromthenorth.com/trim-down-twitter-api-responses-with-cakephps-set-extract/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 12:56:08 +0000</pubDate>
		<dc:creator>kettle</dc:creator>
		
		<category><![CDATA[server-side]]></category>

		<category><![CDATA[api]]></category>

		<category><![CDATA[cakePHP]]></category>

		<category><![CDATA[set::extract]]></category>

		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://cutfromthenorth.com/?p=123</guid>
		<description><![CDATA[I&#8217;ve been working a lot with the Twitter API lately; it&#8217;s been a frustrating experience, especially after being spoiled by the substantially more robust Facebook platform.  One issue of particular concern was the volume of data being returned per request.  
I am caching the response data, and I found that retrieving a list [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working a lot with the Twitter API lately; it&#8217;s been a frustrating experience, especially after being spoiled by the substantially more robust Facebook platform.  One issue of particular concern was the volume of data being returned per request.  </p>
<p>I am caching the response data, and I found that retrieving a list of 100 followers was storing over 150KB of cached data.  One popular Twitter user could then easily be accounting for well over 1MB of cache files.  I only needed about 4 fields from the XML response.  I also knew the <a href="http://book.cakephp.org/view/640/Set" target="_blank">cakePHP Set class</a> was the answer; I just didn&#8217;t know which method.  So after a lot of trial and error, I figured out how to cut the fat with <a href="http://book.cakephp.org/view/671/extract" target="_blank">Set::extract</a>.  I&#8217;m not sure if this is the most efficient solution; also not sure if my regular expression is efficient&#8230; never did take the time to learn regular expressions.  But my cache files are now ~18k vs. the ~150k they used to be.</p>
<p>I&#8217;m using the <a href="http://bakery.cakephp.org/articles/view/twitter-datasource" target="_blank">Twitter datasource</a> which transforms Twitter&#8217;s XML response into an array.  This is necessary as Set::extract expects an array, not an XML object.  Assuming a <code>$followers</code> array:</p>
<pre class="brush: php;">
$followers = Set::extract($followers, 'Users.User.{n}.{(id|name|profile_image_url|screen_name)}');
</pre>
<p>The <code>{n}</code> wildcard will allow every numeric key within <code>['Users']['User']</code> to survive the extract.<br />
The <code>{(id|name|profile_image_url|screen_name)}</code> keeps only the data that maps to those keys (id, name, profile_image_url and screen_name); therefore my $followers array is reduced to:</p>
<pre class="brush: php;">
Array
(
    [0] =&gt; Array
        (
            [id] =&gt; XXXXXXXX
            [name] =&gt; XXXXXXXX
            [screen_name] =&gt; XXXXXXXX
            [profile_image_url] =&gt; XXXXXXXX
        )

    [1] =&gt; Array
        (
            [id] =&gt; XXXXXXXX
            [name] =&gt; XXXXXXXX
            [screen_name] =&gt; XXXXXXXX
            [profile_image_url] =&gt; XXXXXXXX
        )
}
</pre>
<p>There&#8217;s some initial processing overhead, but I&#8217;m sure that will be more than offset by iterating through a much lighter array in the various actions.</p>
]]></content:encoded>
			<wfw:commentRss>http://cutfromthenorth.com/trim-down-twitter-api-responses-with-cakephps-set-extract/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Integrating Facebook Connect with CakePHP&#8217;s Auth component</title>
		<link>http://cutfromthenorth.com/integrating-facebook-connect-with-cakephps-auth-component/</link>
		<comments>http://cutfromthenorth.com/integrating-facebook-connect-with-cakephps-auth-component/#comments</comments>
		<pubDate>Tue, 26 May 2009 01:20:57 +0000</pubDate>
		<dc:creator>kettle</dc:creator>
		
		<category><![CDATA[client-side]]></category>

		<category><![CDATA[server-side]]></category>

		<category><![CDATA[auth]]></category>

		<category><![CDATA[cakePHP]]></category>

		<category><![CDATA[Facebook Connect]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://cutfromthenorth.com/?p=85</guid>
		<description><![CDATA[I wanted to be able to leverage all of the advantages of using Cake&#8217;s built in Auth component in my latest application; problem was that the application needed to allow for both normal user accounts and Facebook Connect generated user accounts.  I struggled for a while to find the most seamless approach, and then [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to be able to leverage all of the advantages of using Cake&#8217;s built in Auth component in my latest application; problem was that the application needed to allow for both normal user accounts and Facebook Connect generated user accounts.  I struggled for a while to find the most seamless approach, and then it clicked &#8212; dynamically set <code>Auth->fields</code>.</p>
<p>First, drop the facebook client libraries in a app/vendors/facebook folder.  Then, in your app_controller, import the classes, and set some properties:</p>
<pre class="brush: php;">
&lt;?php
App::import('Vendor', 'facebook/facebook');

class AppController extends Controller {
    var $components = array('Auth');
    var $uses = array('User');
    var $facebook;
    var $__fbApiKey = 'your_key';
    var $__fbSecret = 'your_secret';
}
</pre>
<p>Next we&#8217;ll overwrite the inherited  <code>__construct</code> method to instantiate a Facebook Object:</p>
<pre class="brush: php;">
	function __construct() {
		parent::__construct();

		// Prevent the 'Undefined index: facebook_config' notice from being thrown.
		$GLOBALS['facebook_config']['debug'] = NULL;

		// Create a Facebook client API object.
		$this-&gt;facebook = new Facebook($this-&gt;__fbApiKey, $this-&gt;__fbSecret);
	}
</pre>
<p>In our <code>beforeFilter</code> method, we define the default <code>Auth</code> properties, call a private <code>__checkFBStatus</code> method, and pass any user data to the view:</p>
<pre class="brush: php;">
function beforeFilter() {
    // Authentication settings
    $this-&gt;Auth-&gt;fields = array('username' =&gt; 'email', 'password' =&gt; 'password');
    $this-&gt;Auth-&gt;logoutRedirect = '/';

    //check to see if user is signed in with facebook
    $this-&gt;__checkFBStatus();

    //send all user info to the view
    $this-&gt;set('user', $this-&gt;Auth-&gt;user());
}
</pre>
<p>Next we&#8217;ll define the private method <code>__checkFBStatus</code> that&#8217;s called in our <code>beforeFilter</code> method.  First we check to make sure <code>$this->Auth->User</code> isn&#8217;t already set by a normal user account, and we check to see if there&#8217;s a logged in facebook user.  The logged in facebook user is available after we use the JavaScript API to log facebook users into the site.</p>
<pre class="brush: php;">
    private function __checkFBStatus(){
        //check to see if a user is not logged in, but a facebook user_id is set
        if(!$this-&gt;Auth-&gt;User() &amp;&amp; $this-&gt;facebook-&gt;get_loggedin_user()):
</pre>
<p>Next, see if this user has already logged in, and therefore already has an entry in our User table:</p>
<pre class="brush: php;">
            //see if this facebook id is in the User database; if not, create the user using their fbid hashed as their password
            $user_record =
                $this-&gt;User-&gt;find('first', array(
                    'conditions' =&gt; array('fbid' =&gt; $this-&gt;facebook-&gt;get_loggedin_user()),
                    'fields' =&gt; array('User.fbid', 'User.fbpassword', 'User.password'),
                    'contain' =&gt; array()
                ));
</pre>
<p>If no record was found, we create a new record for this user. We are setting 3 variables, <code>fbid</code>, <code>fbpassword</code>, and <code>password</code>.  The fbpassword field will hold a randomly generated 20 character string un-hashed so that we can access the value of the field directly from the database.  We retrieve this value based on the fbid field, hash it, and that&#8217;s our password as the Auth Component expects:</p>
<pre class="brush: php;">
            //create new user
            if(empty($user_record)):
                $user_record['fbid'] = $this-&gt;facebook-&gt;get_loggedin_user();
                $user_record['fbpassword'] = $this-&gt;__randomString();
                $user_record['password'] = $this-&gt;Auth-&gt;password($user_record['fbpassword']);

                $this-&gt;User-&gt;create();
                $this-&gt;User-&gt;save($user_record);
            endif;
</pre>
<p>We need to then update our Auth Component&#8217;s fields property to use <code>fbid</code> as the username.</p>
<pre class="brush: php;">
            //change the Auth fields
            $this-&gt;Auth-&gt;fields = array('username' =&gt; 'fbid', 'password' =&gt; 'password');

            //log in the user with facebook credentials
            $this-&gt;Auth-&gt;login($user_record);

        endif;
    }
</pre>
<p>Here&#8217;s the complete <code>app_controller.php</code>:</p>
<pre class="brush: php;">
&lt;?php
App::import('Vendor', 'facebook/facebook');

class AppController extends Controller {
    var $components = array('Auth');
    var $uses = array('User');
	var $facebook;
	var $__fbApiKey = 'your_key';
	var $__fbSecret = 'your_secret';

	function __construct() {
		parent::__construct();

		// Prevent the 'Undefined index: facebook_config' notice from being thrown.
		$GLOBALS['facebook_config']['debug'] = NULL;

		// Create a Facebook client API object.
		$this-&gt;facebook = new Facebook($this-&gt;__fbApiKey, $this-&gt;__fbSecret);
	}

    function beforeFilter() {
		// Authentication settings
		$this-&gt;Auth-&gt;fields = array('username' =&gt; 'email', 'password' =&gt; 'password');
		$this-&gt;Auth-&gt;logoutRedirect = '/';

        //check to see if user is signed in with facebook
        $this-&gt;__checkFBStatus();

        //send all user info to the view
        $this-&gt;set('user', $this-&gt;Auth-&gt;user());
	}

    private function __checkFBStatus(){
        //check to see if a user is not logged in, but a facebook user_id is set
        if(!$this-&gt;Auth-&gt;User() &amp;&amp; $this-&gt;facebook-&gt;get_loggedin_user()):

            //see if this facebook id is in the User database; if not, create the user using their fbid hashed as their password
            $user_record =
                $this-&gt;User-&gt;find('first', array(
                    'conditions' =&gt; array('fbid' =&gt; $this-&gt;facebook-&gt;get_loggedin_user()),
                    'fields' =&gt; array('User.fbid', 'User.fbpassword', 'User.password'),
                    'contain' =&gt; array()
                ));

            //create new user
            if(empty($user_record)):
                $user_record['fbid'] = $this-&gt;facebook-&gt;get_loggedin_user();
                $user_record['fbpassword'] = $this-&gt;__randomString();
                $user_record['password'] = $this-&gt;Auth-&gt;password($user_record['fbpassword']);

                $this-&gt;User-&gt;create();
                $this-&gt;User-&gt;save($user_record);
            endif;

            //change the Auth fields
            $this-&gt;Auth-&gt;fields = array('username' =&gt; 'fbid', 'password' =&gt; 'password');

            //log in the user with facebook credentials
            $this-&gt;Auth-&gt;login($user_record);

        endif;
    }

    private function __randomString($minlength = 20, $maxlength = 20, $useupper = true, $usespecial = false, $usenumbers = true){
        $charset = &quot;abcdefghijklmnopqrstuvwxyz&quot;;
        if ($useupper) $charset .= &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;;
        if ($usenumbers) $charset .= &quot;0123456789&quot;;
        if ($usespecial) $charset .= &quot;~@#$%^*()_+-={}|][&quot;;
        if ($minlength &gt; $maxlength) $length = mt_rand ($maxlength, $minlength);
        else $length = mt_rand ($minlength, $maxlength);
        $key = '';
        for ($i=0; $i&lt;$length; $i++){
            $key .= $charset[(mt_rand(0,(strlen($charset)-1)))];
        }
        return $key;
    }

}
?&gt;
</pre>
<p>Next we need to make a few changes to our default.ctp layout; first add the facebook namespace:</p>
<pre class="brush: xml;">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xmlns:fb=&quot;http://www.facebook.com/2008/fbml&quot;&gt;
</pre>
<p>Add these 2 javascript snippets (be sure your <a href="http://wiki.developers.facebook.com/index.php/Cross-domain_communication_channel" target="_blank">xd_receiver.htm</a> file is accessible in your webroot):</p>
<pre class="brush: xml;">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;FB.init(&quot;your_api_key&quot;,&quot;/xd_receiver.htm&quot;);&lt;/script&gt;
</pre>
<p>Last step, place your login and logout buttons in your default view.  Few things to point out here; <code>onlogin="window.location.reload();"</code> will cause the page to reload after a successful Facebook Connect login.  This is how we are able to access <code>$this->facebook->get_loggedin_user()</code> in our <code>app_controller</code> to force the manual Auth login.  If the user is a facebook user (determined with <code>$user['User']['fbid'] &gt; 0</code>), add an onclick event that calls the <code>FB.Connect.logout()</code> function with a redirect URL as the parameter.  This will log the User out of the Auth Component after it logs the user out of Facebook.</p>
<pre class="brush: php;">
&lt;?php
            if(!empty($user)):
                if($user['User']['fbid'] &gt; 0):
                    echo $html-&gt;link('logout', '#', array('onclick' =&gt; 'FB.Connect.logout(function() { document.location = \'http://your_server/users/logout/\'; }); return false;'));
                else:
                    echo $html-&gt;link('logout', array('controller' =&gt; 'users', 'action' =&gt; 'logout'));
                endif;
            else:
                echo '&lt;fb:login-button onlogin=&quot;window.location.reload();&quot;&gt;&lt;/fb:login-button&gt;';
            endif;
?&gt;
</pre>
<p>One last thing to consider, for security reasons&#8230; In your login method, be sure only users with <code>fbid = 0</code> can login via the normal auth fields (username / password).  Just an extra precaution considering you have an unhashed password in your database for those facebook users.</p>
<p>Hope that helps someone else out.  Let me know if you run into any problems, I slapped this post up quickly and hopefully didn&#8217;t make many mistakes.  And per Matt&#8217;s spot-on recommendation (via <a href="http://pseudocoder.com" target="_blank">pseudocoder.com</a>), I&#8217;m working on rolling this into a plugin&#8230; Will post when it&#8217;s complete.</p>
]]></content:encoded>
			<wfw:commentRss>http://cutfromthenorth.com/integrating-facebook-connect-with-cakephps-auth-component/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mobile device detection and development with CakePHP</title>
		<link>http://cutfromthenorth.com/mobile-device-detection-and-development-with-cakephp/</link>
		<comments>http://cutfromthenorth.com/mobile-device-detection-and-development-with-cakephp/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 22:26:28 +0000</pubDate>
		<dc:creator>kettle</dc:creator>
		
		<category><![CDATA[server-side]]></category>

		<category><![CDATA[cakePHP]]></category>

		<category><![CDATA[mobile]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://cutfromthenorth.com/?p=36</guid>
		<description><![CDATA[I was recently working on a project that required a mobile version of the site (built with cakePHP).  The site was simple enough that the majority of the actions that rendered views were contained within one controller.  Using cake&#8217;s built in Request Handling makes it easy to detect mobile devices and select an [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently working on a project that required a mobile version of the site (built with cakePHP).  The site was simple enough that the majority of the actions that rendered views were contained within one controller.  Using cake&#8217;s built in <a href="http://book.cakephp.org/view/174/Request-Handling" target="_blank">Request Handling</a> makes it easy to detect mobile devices and select an appropriate view and layout file to render the action.</p>
<p>In your app_controller.php, turn off autoRender if the isMobile method returns true:</p>
<pre class="brush: php;">
// file: /app/app_controller.php
class AppController extends Controller {
    var $components = array('RequestHandler');

    function beforeFilter(){
        if ($this-&gt;RequestHandler-&gt;isMobile()) {
            $this-&gt;autoRender = false;
        }
    }

    function afterFilter(){
        if ($this-&gt;RequestHandler-&gt;isMobile()) {
            $this-&gt;render($this-&gt;action, 'mobile', 'mobile_'.$this-&gt;action);
        }
    }
}
</pre>
<p>The afterFilter function runs the same conditional statement as beforeFilter, but tells cake to render the currently running action using the &#8216;mobile&#8217; layout, using the &#8216;mobile_action&#8217; view.  So when you create your normal view files, also create a mobile version with the same file name, preceeded with &#8216;mobile_&#8217;.  This approach assumes you want to run the same controller logic for both versions of the site (mobile and standard).  You could always use routes to create a more elegant system for handling requests from mobile devices, but for this particular project, the logic didn&#8217;t change much beyond defining the default limit with pagination.</p>
<p>And don&#8217;t forget, if you&#8217;re defining afterFilter and beforeFilter in your app_controller, be sure your controllers inherit app_controller&#8217;s filter functions.</p>
<pre class="brush: php;">
// file: /app/controllers/posts_controller.php
class PostsController extends AppController {
    var $name = 'Posts';

    function beforeFilter(){
        parent::beforeFilter();
        //rest of your beforeFilter function here...
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://cutfromthenorth.com/mobile-device-detection-and-development-with-cakephp/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
