<?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>Straylight Run &#187; Coding</title> <atom:link href="http://blog.straylightrun.net/category/coding/feed/" rel="self" type="application/rss+xml" /><link>http://blog.straylightrun.net</link> <description>Software, Technology, PHP</description> <lastBuildDate>Mon, 07 Nov 2011 19:26:59 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Making Blueprint CSS Grid Mobile-Friendly</title><link>http://blog.straylightrun.net/2011/11/07/making-blueprint-css-grid-mobile-friendly/</link> <comments>http://blog.straylightrun.net/2011/11/07/making-blueprint-css-grid-mobile-friendly/#comments</comments> <pubDate>Mon, 07 Nov 2011 19:19:40 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[css]]></category> <category><![CDATA[design]]></category> <category><![CDATA[front-end]]></category> <category><![CDATA[layout]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2011/11/07/making-blueprint-css-grid-mobile-friendly/</guid> <description><![CDATA[I had an existing site I created using Blueprint CSS a while ago. I wanted to make it mobile-friendly. There are responsive CSS grid frameworks out there now, but I didn’t feel like replacing Blueprint, and I figured all I had to do was, using media queries, make every column span a fixed width. That [...]]]></description> <content:encoded><![CDATA[<p>I had an existing site I created using <a
href="http://blueprintcss.org/">Blueprint CSS</a> a while ago. I wanted to make it mobile-friendly. There are <a
href="http://framelessgrid.com/">responsive CSS</a> <a
href="http://getskeleton.com/">grid frameworks</a> out there now, but I didn’t feel like replacing Blueprint, and I figured all I had to do was, using media queries, make every column span a fixed width. That was mostly correct. In the end, I used 100% widths, plus a few other alterations.&#160; Here is how I ended up doing it.</p><p>Normally, you will link to your Blueprint <code>screen.css</code> file like so:</p><div
class="wp_syntax"><div
class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/css/screen.css&quot; media=&quot;screen, projection&quot; /&gt;</pre></div></div><p>The following lines tell the browser to link first to a mobile-friendly CSS file. Then, if and when the width is <code>600px</code>, link to the normal, desktop CSS file. The idea is that bandwidth is scarcer on mobile, so we don&#8217;t mind downloading two files on a desktop machine if we have to.</p><div
class="wp_syntax"><div
class="code"><pre class="html" style="font-family:monospace;">&lt;!-- For mobile displays --&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/css/mobile.css&quot; media=&quot;screen, projection&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/css/print.css&quot; media=&quot;print&quot; /&gt;
&nbsp;
&lt;!-- For desktop displays --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/screen.css&quot; media=&quot;only screen and (min-width: 600px)&quot; /&gt;</pre></div></div><p>To create my <code>mobile.css</code>, I copied <code>screen.css</code>, and made the following changes.</p><ol><li>Change table elements padding to <code>2px</code><p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;">th<span style="color: #00AA00;">,</span> td<span style="color: #00AA00;">,</span> caption <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">2px</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change <code>input</code> text fields to 67% width.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;">input.<span style="color: #993333;">text</span><span style="color: #00AA00;">,</span> input<span style="color: #6666ff;">.title</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">67%</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change <code>textarea</code> inputs to 80% width, and reduce <code>height</code> to <code>150px</code>.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;">textarea <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">80%</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">150px</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change the overall <code>container</code> to 100% width.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.container</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333;">auto</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change all <code>span</code> grid classes to 100% width.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.span-1</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span>
...
<span style="color: #6666ff;">.span-24</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">margin-right</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>For some reason, I ended up deleting all <code>input.span</code> and <code>textarea.span</code> classes, though I&#8217;m not sure why now.</li><li>Change all <code>append</code> grid classes to <code>0px</code> right padding.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.append-1</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">padding-right</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span>
...
<span style="color: #6666ff;">.append-24</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">padding-right</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change all <code>prepend</code> grid classes to <code>0px</code> left padding.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.prepend-1</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">padding-left</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span>
...
<span style="color: #6666ff;">.prepend-24</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">padding-left</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change all <code>pull</code> grid classes to <code>0px</code> left margin.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.pull-1</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">margin-left</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span>
...
<span style="color: #6666ff;">.pull-24</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">margin-left</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li><li>Change all <code>push</code> grid classes to <code>0px</code> margin.<p></p><div
class="wp_syntax"><div
class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.push-1</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span>
...
<span style="color: #6666ff;">.push-24</span> <span style="color: #00AA00;">&#123;</span><span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span><span style="color: #00AA00;">&#125;</span></pre></div></div></li></ol><p>Not pretty, but it seems to work well.&#160; Happy CSS!</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2011/11/07/making-blueprint-css-grid-mobile-friendly/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>My Facebook Authentication Best Practices</title><link>http://blog.straylightrun.net/2011/09/19/my-facebook-authentication-best-practices/</link> <comments>http://blog.straylightrun.net/2011/09/19/my-facebook-authentication-best-practices/#comments</comments> <pubDate>Mon, 19 Sep 2011 22:17:09 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[authentication]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[oauth]]></category> <category><![CDATA[oauth2]]></category> <category><![CDATA[sdk]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2011/09/19/my-facebook-authentication-best-practices/</guid> <description><![CDATA[NOTE: I had a version of this blog post in draft mode for months addressing the old (PHP SDK v2.1.2) Facebook PHP library.&#160; In a fit of momentum, I am publishing this post now, updated to use the new library (PHP SDK v3.1.1).&#160; Since I am not as familiar with the new one, there may [...]]]></description> <content:encoded><![CDATA[<p><em><strong>NOTE: </strong>I had a version of this blog post in draft mode for months addressing the old (PHP SDK v2.1.2) Facebook PHP library.&#160; In a fit of momentum, I am publishing this post now, updated to use the new library (PHP SDK v3.1.1).&#160; Since I am not as familiar with the new one, there may be better ways to do the following, although the code below works.</em></p><p>Facebook authentication, much like the rest of the platform, can be maddening.&#160; It appears easy enough at 1st glance, until you realize the <a
href="https://developers.facebook.com/docs/guides/web/#login">contrived XFBML examples in the docs</a> will not get you very far.&#160; So then you might take a look at the <a
href="https://developers.facebook.com/docs/authentication/">advanced document</a>. And then realize that the advance document, that giant, complicated, very detailed and thorough explanation of OAuth 2.0 as implemented by Facebook, <em>does not actually</em> help you code your website.</p><p>This blog post is more for my benefit than yours, and serves to summarize my current Facebook authentication strategy, so I don’t have to figure it out over and over. At least, until Facebook changes it.</p><p><strong><u>My Requirements</u></strong></p><p>First off, realize that there are 3 ways to do any particular thing on the Facebook platform: XFBML, JS, and PHP (server-side).</p><p>That said, I do not use the XFBML <code>&lt;fb:login/&gt;</code> button.&#160; XFBML is great for non-developers who can copy and paste the documentation into a website and impress their friends.&#160; But XFBML is slower, ties your user’s application session to your user’s Facebook session, and you can’t make general API calls, so you may as well learn how to use the JS or PHP SDKs anyway.</p><ol><li>Authentication flow must work with and without JavaScript, as we are targeting older smart phones, such as Blackberry Curves.</li><li>I do not want to use Facebook to <em>persist</em> my application sessions.&#160; I merely want to use Facebook for <em>authentication</em> and then use standard PHP sessions to maintain a user login.&#160; Using the Facebook session <em>as your </em>application session (as in the case of XFBML above) is sucky.&#160; You will noticed sites that do this because when you log out of the site, you will log out of Facebook, and vice-versa.&#160; Logging out of your site <em>should not </em>log you out of Facebook.&#160; Facebook sessions and your application’s session should be separate.&#160; I want to use Facebook only to <em>authenticate</em> the user, that is, to confirm the user is who they say they are.&#160; <a
href="http://foursquare.com">Foursquare</a> does a great job of this.</li></ol><p><strong><u>Implementation</u></strong></p><p>First, I need a login login link that non-JS browsers can use.</p><div
class="wp_syntax"><div
class="code"><pre class="html" style="font-family:monospace;">&lt;a id=&quot;fb-login&quot; href=&quot;&lt;?= $loginUrl ?&gt;&quot;&gt;Login&lt;/a&gt;</pre></div></div><p>That <code>$loginUrl</code> comes from:</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$loginUrl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$facebook</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLoginUrl</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'scope'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'offline_access'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>The login link will ask the user for <code>offline_access </code>permission, as an example.</p><p>Then we need some the FB JS SDK to handle the link for those of us with modern browsers.</p><div
class="wp_syntax"><table><tr><td
class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td
class="code"><pre class="javascript" style="font-family:monospace;">FB.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> appId<span style="color: #339933;">:</span> <span style="color: #3366CC;">'XXXXXX'</span><span style="color: #339933;">,</span> <span style="color: #000066;">status</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> cookie<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> oauth<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#fb-login'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  e.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  FB.<span style="color: #660066;">getLoginStatus</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// maintain application anchor/query string, if any</span>
    q <span style="color: #339933;">=</span> window.<span style="color: #660066;">location</span>.<span style="color: #660066;">search</span>.<span style="color: #660066;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>window.<span style="color: #660066;">location</span>.<span style="color: #660066;">hash</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      q <span style="color: #339933;">=</span> window.<span style="color: #660066;">location</span>.<span style="color: #660066;">hash</span>.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'?'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// if already logged in, redirect</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>response.<span style="color: #660066;">authResponse</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      window.<span style="color: #660066;">location</span>.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'/?signed_request='</span> <span style="color: #339933;">+</span> response.<span style="color: #660066;">authResponse</span>.<span style="color: #660066;">signedRequest</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&amp;'</span> <span style="color: #339933;">+</span> q<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">// else present user with FB auth popup</span>
      FB.<span style="color: #660066;">login</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// if user logs in successfully, redirect</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>response.<span style="color: #660066;">authResponse</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          window.<span style="color: #660066;">location</span>.<span style="color: #660066;">href</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'/?signed_request='</span> <span style="color: #339933;">+</span> response.<span style="color: #660066;">authResponse</span>.<span style="color: #660066;">signedRequest</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&amp;'</span> <span style="color: #339933;">+</span> q<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> scope<span style="color: #339933;">:</span><span style="color: #3366CC;">'offline_access'</span> <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div><p>Couple interesting things to point out:</p><ol><li>In the call to <a
href="https://developers.facebook.com/docs/reference/javascript/FB.init/"><code>FB.init()</code></a>, the <code>cookie </code>flag is set to <code>false</code>.&#160; In most FB examples, this flag is set to <code>true</code>.&#160; If this flag is <code>true</code>, the JS will set a cookie (that begins with ‘<code>fbsr_</code>’) that will keep the user connected to your Facebook app during a browser session.&#160; This can confuse your app, because if you do not clear this cookie when your user logs out, your app may automatically re-authenticate your user.&#160; If you <em>do </em>intend to use your user’s Facebook session as your website’s session, set this flag to <code>true</code>.</li><li>On lines 16 and 25, as in most FB examples, a simple <code>window.location.reload()</code> might appear.&#160; This only works if the JS sets the Facebook cookie, as this cookie will tell the server that the user is authenticated after the reload.&#160; Since we can’t use the cookie, we need another way to tell the server if this login attempt was successful.</li></ol><p><strong><u>Server side</u></strong></p><p>On the server-side, Facebook will tell us if this user is who he says he is with the <a
href="https://developers.facebook.com/docs/reference/php/facebook-getUser/"><code>getUser()</code></a> method.&#160; If this method returns a non-zero user ID, then Facebook has authenticated this user, and we can create a normal PHP login session, however you usually do that.</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$facebook</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// login successful</span>
    <span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// redirect to user dashboard or something</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP/1.1 302 Found'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: /'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">exit</span><span style="color: #339933;">;</span></pre></div></div><p><code>getUser()</code> tries to authenticate a few different ways.&#160; You can read the code in the <a
href="https://github.com/facebook/php-sdk/blob/v3.1.1/src/base_facebook.php#L408">PHP SDK</a> if you’re really curious. One way is from the ‘<code>fbsr_</code>’ cookie.&#160; Another is by checking for the <code>signed_request </code>in the query string.&#160; Remember when we passed that in earlier via JS?&#160;&#160; The cool thing is, that even in the non-JS case, Facebook will send that <code>signed_request </code>in the query string, so this code will function the same in both cases.</p><p>Keeping the user logged in as he makes requests is the same as usual.&#160; I simply check for the flag (or, in the example above, a user ID) to verify authenticated status.</p><p>To logout, I can simply clear the PHP session like normal.</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// logout</span>
<span style="color: #990000;">session_unset</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">session_destroy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// redirect to external home page</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP/1.1 302 Found'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: /'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">exit</span><span style="color: #339933;">;</span></pre></div></div><p>Again, this does not log me out of Facebook</p><p><u><strong>Conclusion</strong></u></p><p>When might you want to use your user’s Facebook session for your user’s website session?&#160; I think the only case you would do that is if your web app is a Facebook-centric application.&#160; That is, if every feature of your app involves Facebook somehow. In that case, maybe it makes sense because your user cannot use your app without being connected to Facebook.</p><p>You can find a fully working example of this flow on my <a
href="https://github.com/hellogerard/facebook-auth">GitHub</a>.&#160; This really belongs in an MVC-type framework, but for simplicity I put everything in a giant <code>if/else </code>statement.&#160; Throw the files in a webroot, add your app’s ID and secret to the PHP file, and try it out. Try it with JavaScript enabled and disabled.&#160; After logging into the example, try logging out of Facebook, and then logging out of the example, and vice-versa. And let me know if you spot anything fishy.</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2011/09/19/my-facebook-authentication-best-practices/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Facebook: Upgrading to OAuth 2.0</title><link>http://blog.straylightrun.net/2011/09/19/facebook-upgrading-to-oauth-2-0/</link> <comments>http://blog.straylightrun.net/2011/09/19/facebook-upgrading-to-oauth-2-0/#comments</comments> <pubDate>Mon, 19 Sep 2011 18:01:44 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[authentication]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[oauth]]></category> <category><![CDATA[oauth2]]></category> <category><![CDATA[sdk]]></category> <category><![CDATA[upgrading]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2011/09/19/facebook-upgrading-to-oauth-2-0/</guid> <description><![CDATA[As Facebook has beaten into me via my RSS reader over the last few months: All apps must migrate to OAuth 2.0 for authentication and expect an encrypted access token. The old SDKs, including the old JS SDK and old iOS SDK will no longer work. &#60;digression&#62; In the spirit of typical Facebook developer documentation, [...]]]></description> <content:encoded><![CDATA[<p>As Facebook has beaten into me via my RSS reader over the last few months:</p><blockquote><p>All apps must <a
href="https://developers.facebook.com/docs/oauth2-https-migration/">migrate to OAuth 2.0 for authentication</a> and expect an encrypted access token. The old SDKs, including the old JS SDK and old iOS SDK will no longer work.</p></blockquote><p>&lt;digression&gt; In the spirit of typical Facebook developer documentation, even this ostensibly unambiguous statement raises questions.&#160; See, I have been using the “new” Graph API to authenticate for many months now, but not with the <code>oauth </code>flag set to <code>true</code>.&#160; (In other words, I am on Oauth 1.0?)&#160; Does this mean my code will break on Oct. 1st?&#160; Or when they say that legacy authentication will break on Oct. 1st, do they mean that only the <em><a
href="https://developers.facebook.com/docs/authentication/connect_auth/">really old legacy auth</a></em> will break?&#160; In either case, I may as well upgrade to the latest and greatest now. &lt;/digression&gt;</p><p>Here are the changes I had to make to get my stuff working with the <code>oauth </code>flag set to <code>true</code>.&#160; They are mostly field and param name changes.&#160; There may be other changes important to you, but this is what I needed to modify to upgrade.</p><h6><strong><u>1. Add &#8216;<code>oauth: true</code>&#8216; to </u><a
href="https://developers.facebook.com/docs/reference/javascript/FB.init/"><code>FB.init()</code></a></strong></h6><p>So change this:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">FB.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> appId <span style="color: #339933;">:</span> XXXXXX <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>to this:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">FB.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> appId <span style="color: #339933;">:</span> XXXXXX<span style="color: #339933;">,</span> oauth <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>I infer from Facebook (which is usually dangerous) that this flag will be enabled for everyone on Oct. 1st.</p><p><strong><u>2. Change &#8216;<code>perms</code>&#8216; to &#8216;<code>scope</code>&#8216; </u></strong></p><p>Anywhere you request permissions for your app upon Facebook login, you must change the ‘<code>perms</code>’ field to ‘<code>scope</code>’. So for a typical XFBML implementation, change this:</p><div
class="wp_syntax"><div
class="code"><pre class="html" style="font-family:monospace;">&lt;fb:login-button perms=”offline_access”&gt;&lt;/fb:login-button&gt;</pre></div></div><p>to this:</p><div
class="wp_syntax"><div
class="code"><pre class="html" style="font-family:monospace;">&lt;fb:login-button scope=”offline_access”&gt;&lt;/fb:login-button&gt;</pre></div></div><p>For a typical JS implementation, change this:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">FB.<span style="color: #660066;">login</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> perms <span style="color: #339933;">:</span> ‘offline_access’ <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>to this:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">FB.<span style="color: #660066;">login</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> scope <span style="color: #339933;">:</span> ‘offline_access’ <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>For a typical non-JS, server-side (PHP) implementation, change this:</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;">&lt;a href=”<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$facebook</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLoginUrl</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>‘req_perms’ <span style="color: #339933;">=&gt;</span> ‘offline_acces<span style="color: #0000ff;">'s’)); ?&gt;</span>”&gt;Connect with Facebook&lt;/a&gt;</pre></div></div><p>to this:</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;">&lt;a href=”<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$facebook</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLoginUrl</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>‘scope’ <span style="color: #339933;">=&gt;</span> ‘offline_acces<span style="color: #0000ff;">'s’)); ?&gt;</span>”&gt;Connect with Facebook&lt;/a&gt;</pre></div></div><p><strong><u>3. Update JavaScript response object</u></strong></p><p>Functions like <a
href="https://developers.facebook.com/docs/reference/javascript/FB.login/"><code>FB.login()</code></a> and <a
href="https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/"><code>FB.getLoginStatus()</code></a> accept a callback that gets passed a response object from Facebook after an authentication attempt.&#160; The previous response looked like this:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">response <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> perms <span style="color: #339933;">:</span> ‘offline_access’<span style="color: #339933;">,</span>
             session <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
               access_token <span style="color: #339933;">:</span> ‘XXXXXX’<span style="color: #339933;">,</span>
               base_domain <span style="color: #339933;">:</span> ‘mydomain.<span style="color: #660066;">com</span>’<span style="color: #339933;">,</span>
               expires <span style="color: #339933;">:</span> ‘<span style="color: #CC0000;">0</span>’<span style="color: #339933;">,</span>
               secret <span style="color: #339933;">:</span> ‘XXXXXX’<span style="color: #339933;">,</span>
               session_key <span style="color: #339933;">:</span> ‘XXXXXX’<span style="color: #339933;">,</span>
               sig <span style="color: #339933;">:</span> ‘XXXXXX’<span style="color: #339933;">,</span>
               uid <span style="color: #339933;">:</span> ‘XXXXXX’ <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
             <span style="color: #000066;">status</span> <span style="color: #339933;">:</span> ‘connected’ <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>The new response looks like this:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">response <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> authResponse <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
               accessToken <span style="color: #339933;">:</span> ‘XXXXXX’<span style="color: #339933;">,</span>
               expiresIn <span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>
               signedRequest <span style="color: #339933;">:</span> ‘XXXXXX’<span style="color: #339933;">,</span>
               userID <span style="color: #339933;">:</span> ‘XXXXXX’ <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
             <span style="color: #000066;">status</span> <span style="color: #339933;">:</span> ‘connected’ <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>You must update your JS authentication logic accordingly.</p><p><strong><u>4. Change server-side PHP call getSession() to </u><a
href="https://developers.facebook.com/docs/reference/php/facebook-getUser/">getUser()</a></strong></p><p>Versions of the PHP SDK prior to 3.0 had both a <code>getSession()</code> and a <code>getUser()</code> method. After 3.0, there is only the <code>getUser()</code> call.&#160; If you were using <code>getSession() </code>to check for authentication previously, you must use <code>getUser() </code>now.&#160; If you don’t care about the internals of the new SDK, then <code>getUser() </code>functions the same as before and returns the Facebook ID of the currently logged in user, or 0 if there is none.</p><p>If you do care about the new SDK, then the reason for this is because Facebook has done away with the session concept and embraced the OAuth2 <a
href="https://developers.facebook.com/docs/authentication/signed_request/"><code>signed_request</code></a> concept instead.&#160; For example, the JSON-ified session array is no longer passed back to your callback URL in the query string upon authentication.&#160; Now, an encoded signed_request is passed back in the query string, which contains the same info (user ID, access token, expiration time, etc.)</p><p><strong><u>5. Change server-side PHP Facebook class constructor</u></strong></p><p>The new PHP Facebook class no longer accepts a <code>cookie </code>flag in the constructor.&#160; If you don’t care about the internals of the new SDK, then remove the cookie flag and you’re done.</p><p>If you do care about the new SDK, then the reason for this – well, I’m not sure what the reason is.&#160; Perhaps a commenter could enlighten me.&#160; Best as I can tell, they have removed overlapping features of the the JS SDK and PHP SDK. Prior to OAuth2, both SDKs had cookie flags, and both could set and read the session cookie, which could be confusing, especially if you were persisting your own authentication cookie.&#160; Now, the JS can still set and read the <code>signed_request </code>cookie, but the PHP library has gotten out of the cookie game (although it can still read a <code>signed_request </code>cookie set by JS, and now it stores the <code>signed_request </code>data in the PHP session).</p><p>One more note about cookie: the new Facebook cookie begins with ‘<code>fbsr_</code>’ and not ‘<code>fbs_</code>’.</p><p><u><strong>Conclusion</strong></u></p><p>That’s it. As I said, these worked for me, but YMMV. Happy upgrading!</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2011/09/19/facebook-upgrading-to-oauth-2-0/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Slides from tek11</title><link>http://blog.straylightrun.net/2011/05/28/slides-from-tek11/</link> <comments>http://blog.straylightrun.net/2011/05/28/slides-from-tek11/#comments</comments> <pubDate>Sat, 28 May 2011 17:34:48 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Career]]></category> <category><![CDATA[Coding]]></category> <category><![CDATA[conferences]]></category> <category><![CDATA[cookies]]></category> <category><![CDATA[sessions]]></category> <category><![CDATA[software]]></category> <category><![CDATA[talks]]></category> <category><![CDATA[tek]]></category> <category><![CDATA[tek11]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2011/05/28/slides-from-tek11/</guid> <description><![CDATA[Here are my slides from my two talks at PHP 2011 tek conference in Chicago, IL.&#160; Slide PDFs and any demo code are on GitHub.&#160; Recap to follow! Of (PHP) Sessions, Cookies, and Authentication Do you know the difference between the PHP config directives session.gc_maxlifetime and session.cookie_lifetime? Have you wrestled with implementing a “Remember Me” [...]]]></description> <content:encoded><![CDATA[<p>Here are my slides from my two talks at PHP 2011 tek conference in Chicago, IL.&#160; <a
href="https://github.com/hellogerard/tek11">Slide PDFs and any demo code are on GitHub</a>.&#160; Recap to follow!</p><blockquote><p><u>Of (PHP) Sessions, Cookies, and Authentication</u></p><p>Do you know the difference between the PHP config directives <code>session.gc_maxlifetime</code> and <code>session.cookie_lifetime</code>? Have you wrestled with implementing a “Remember Me” button on your login page? Learn how popular sites, such as Twitter and Facebook, keep you logged in (apparently) forever and the security risks of such methods.</p></blockquote><div
style="width: 425px" id="__ss_8116440"><strong
style="margin: 12px 0px 4px; display: block"><a
title="PHP Cookies, Sessions and Authentication" href="http://www.slideshare.net/gerrys0/php-cookies-sessions-and-authentication">PHP Cookies, Sessions and Authentication</a></strong> <iframe
height="355" marginheight="0" src="http://www.slideshare.net/slideshow/embed_code/8116440" frameborder="0" width="425" marginwidth="0" scrolling="no"></iframe><div
style="padding-bottom: 12px; padding-left: 0px; padding-right: 0px; padding-top: 5px">View more <a
href="http://www.slideshare.net/">presentations</a> from <a
href="http://www.slideshare.net/gerrys0">Gerard Sychay</a></div></p></div><blockquote><p><u>Who&#8217;s Using Your Software?</u></p><p>Software is only successful if someone can use it. Good developers need to do more than just follow specifications, they need to visualize the people who will use it and understand what they need. Get to know your users and the questions you need to ask to make your implementation a success on all fronts.</p></blockquote><div
style="width: 425px" id="__ss_8129301"><strong
style="margin: 12px 0px 4px; display: block"><a
title="Who&#39;s Using Your Software" href="http://www.slideshare.net/gerrys0/whos-using-your-software">Who&#8217;s Using Your Software</a></strong> <iframe
height="355" marginheight="0" src="http://www.slideshare.net/slideshow/embed_code/8129301" frameborder="0" width="425" marginwidth="0" scrolling="no"></iframe><div
style="padding-bottom: 12px; padding-left: 0px; padding-right: 0px; padding-top: 5px">View more <a
href="http://www.slideshare.net/">presentations</a> from <a
href="http://www.slideshare.net/gerrys0">Gerard Sychay</a></div></p></div> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2011/05/28/slides-from-tek11/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Zend Framework Bootstrap.php (Or, They Hung Him Up By His Bootstraps)</title><link>http://blog.straylightrun.net/2011/04/13/zend-framework-bootstrap-php-or-they-hung-him-up-by-his-bootstraps/</link> <comments>http://blog.straylightrun.net/2011/04/13/zend-framework-bootstrap-php-or-they-hung-him-up-by-his-bootstraps/#comments</comments> <pubDate>Thu, 14 Apr 2011 03:56:11 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[bootstrap]]></category> <category><![CDATA[frameworks]]></category> <category><![CDATA[resources]]></category> <category><![CDATA[zend framework]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2011/04/13/zend-framework-bootstrap-php-or-they-hung-him-up-by-his-bootstraps/</guid> <description><![CDATA[I recently came up a very steep learning curve using the Zend Framework (version 1.11.3). I had used components of ZF in the past with success, but this was the first time I had used Zend_Application for my core MVC.&#160; I am no stranger to MVC frameworks in general, but I struggled with Zend. My [...]]]></description> <content:encoded><![CDATA[<p>I recently came up a very steep learning curve using the <a
href="http://framework.zend.com">Zend Framework</a> (version 1.11.3). I had used components of ZF in the past with success, but this was the first time I had used <a
href="http://framework.zend.com/manual/en/zend.application.html"><code>Zend_Application</code></a> for my core MVC.&#160; I am no stranger to MVC frameworks in general, but I struggled with Zend.</p><p>My biggest source of confusion was the bootstrap process.&#160; Namely, the autoloading of resources.&#160; Yes, I followed the <a
href="http://framework.zend.com/manual/en/learning.quickstart.html">Zend Framework Quick Start</a> and got my app up and running. Unfortunately, I didn’t actually know <em>what was happening</em>.&#160; Finally, I came across this great question on <a
href="http://stackoverflow.com">Stackoverflow</a> about <a
href="http://stackoverflow.com/questions/1074139/zend-framework-layout">bootstrapping the layout resource</a> that pointed me in the right direction:</p><blockquote><p>The line from <code>application.ini</code></p><pre><code>resources.layout[] = </code></pre><p>is equivalent to:</p><pre><code>_initLayout() {}</code></pre><p>in <code>Bootstrap.php</code></p></blockquote><p>Aha!&#160; So now it was clear. There are two ways to initialize a resource in Zend:</p><ol><li>By adding one or more mysterious lines to your application.ini, or</li><li>By constructing them with good old fashion code in a method that begins with “_init” in <code>Bootstrap.php</code>.</li></ol><p>Option #1 bothers me.&#160; Yes, it’s really cool that you can bootstrap a whole MVC application with no code and only a config file, but IMO that option should <em>not</em> be the recommended way for beginners and that options should most definitely <em>not</em> be used in any sort of “Quick Start” guide.&#160; That sort of magic should be reserved for advanced users.&#160; With a little more exploring, I found the code that initialized these resources in the non-trivial <a
href="http://framework.zend.com/code/filedetails.php?repname=Zend+Framework&amp;path=%2Ftrunk%2Flibrary%2FZend%2FApplication%2FBootstrap%2FBootstrapAbstract.php"><code>Zend_Application_Bootstrap_BootstrapAbstract</code></a> class.&#160; And I found all the built-in Zend resources in <a
href="http://framework.zend.com/code/listing.php?repname=Zend+Framework&amp;path=%2Ftrunk%2Flibrary%2FZend%2FApplication%2FResource%2F&amp;#ae42a1368351649c6b01f1d2aadf9e3d3"><code>Zend/Application/Resource</code></a>, which let me see which resources had which options and how to bootstrap them.&#160;</p><p>On to option #2, my preferred way. If I want to initialize the Front Controller, I’ll just put this in the bootstrap file:</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _initFrontController<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$front</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$front</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setControllerDirectory</span><span style="color: #009900;">&#40;</span>APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/controllers'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$front</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>If I want to enable and initialize the layout:</p><div
class="wp_syntax"><div
class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _initLayout<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$layout</span> <span style="color: #339933;">=</span> Zend_Layout<span style="color: #339933;">::</span><span style="color: #004000;">startMvc</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$layout</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLayoutPath</span><span style="color: #009900;">&#40;</span>APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/layouts/scripts/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$layout</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>I really don’t mind carrying this around to every project.&#160; Then I can make changes in the PHP, and not in an INI file.</p><p>Clearly I am not the only one struggling with this. I googled problems heavily and the top results usually contained 3 or 4 of the same question asked on Stackoverflow, each of which I opened in a tab.&#160; I think Zend would benefit with a re-organization of the documentation from the ground up, at least of the starter docs and <code>Zend_Application</code>. They should also post a big, flashing red link to that Stackoverflow question about bootstrapping layout.&#160;</p><p>Eventually, other components became clear: Resources, Plugins, Action Helpers, and View Helpers, Modules.&#160; I see real power in using the Zend Framework now, particularly with Plugins and Modules, but only after much pain.</p><p>I have created a <a
href="https://github.com/hellogerard/zend-starter">starter project for Zend projects</a> that contains <a
href="https://github.com/hellogerard/zend-starter/blob/modules-app/application/Bootstrap.php"><code>Bootstrap.php</code></a> the way I like it, and some other custom classes for logging and error handling.&#160; There is a branch for a starter project <a
href="https://github.com/hellogerard/zend-starter">with modules</a> and <a
href="https://github.com/hellogerard/zend-starter/tree/single-app">without modules</a>.&#160; (Modules is a different blog post altogether.)</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2011/04/13/zend-framework-bootstrap-php-or-they-hung-him-up-by-his-bootstraps/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>A Layout Called By Any Other Name&#8230;</title><link>http://blog.straylightrun.net/2011/04/13/a-layout-called-by-any-other-name/</link> <comments>http://blog.straylightrun.net/2011/04/13/a-layout-called-by-any-other-name/#comments</comments> <pubDate>Thu, 14 Apr 2011 03:44:52 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[layout]]></category> <category><![CDATA[render]]></category> <category><![CDATA[smarty]]></category> <category><![CDATA[view]]></category> <category><![CDATA[zend framework]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2011/04/13/a-layout-called-by-any-other-name/</guid> <description><![CDATA[I am embarrassed to say that only somewhat recently did I figure out truly what a layout-based presentation (a.k.a. two-phase render) was all about. I’ve even used them before, and didn’t know why.&#160; If you can’t tell someone clearly what is the benefit of two-phase render, go and read the Smarty documentation on it right [...]]]></description> <content:encoded><![CDATA[<p>I am embarrassed to say that only somewhat recently did I figure out truly what a layout-based presentation (a.k.a. two-phase render) was all about. I’ve even used them before, and didn’t know why.&#160;</p><p>If you can’t tell someone clearly what is the benefit of two-phase render, go and read the Smarty documentation on it right now.&#160; Smarty calls it <a
href="http://www.smarty.net/inheritance">template inheritance</a>, but IMO template inheritance, layouts, and two-phase render are all the same pattern.</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2011/04/13/a-layout-called-by-any-other-name/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Choosing A Language</title><link>http://blog.straylightrun.net/2010/11/09/choosing-a-language/</link> <comments>http://blog.straylightrun.net/2010/11/09/choosing-a-language/#comments</comments> <pubDate>Tue, 09 Nov 2010 22:32:27 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[language]]></category> <category><![CDATA[platform]]></category> <category><![CDATA[rails]]></category> <category><![CDATA[ruby]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2010/11/09/choosing-a-language/</guid> <description><![CDATA[This post, “14 descriptive reasons why Ruby may be better than PHP,” popped up on PHPDeveloper.org yesterday.&#160; These types of lists appear regularly in the blogosphere. I usually don’t feel compelled to respond, but for some reason this time I do.&#160; Perhaps it is the cool graphics.&#160; Perhaps it is because I just wanted to [...]]]></description> <content:encoded><![CDATA[<p>This post, “<a
href="http://www.webdeveloperjuice.com/2010/11/07/14-descriptive-reasons-why-ruby-is-better-than-php/">14 descriptive reasons why Ruby may be better than PHP</a>,” popped up on <a
href="http://www.phpdeveloper.org">PHPDeveloper.org</a> yesterday.&#160; These types of lists appear regularly in the blogosphere. I usually don’t feel compelled to respond, but for some reason this time I do.&#160; Perhaps it is the cool graphics.&#160; Perhaps it is because I just wanted to blog.</p><p>Speaking as someone who has done <em>a lot</em> of PHP, and <em>very little</em> Ruby or Rails, overall, I agree with the article.&#160; It talks about many of the reasons I wish I could start using Ruby more.&#160; However, I would like to refute a few particular items in the list.&#160; I’ll just cover each one with my input.</p><blockquote><p><strong>1.</strong> Human-readable code.</p><p><a
href="http://en.wikipedia.org/wiki/Yukihiro_Matsumoto">Yukihiro Matsumodo</a> wanted to create a language that was designed for programmer functionality. By keeping naming consistent and keywords sensible, he was able to do so.</p></blockquote><p>Agree.&#160; I think this is more of a result of the object-oriented features of Ruby than anything else, but the names and keywords are indeed nice.</p><blockquote><p><strong>2.</strong> Principle of least surprise</p><p>it is designed in such a way that the language minimizes confusion for experienced users. Methods for different objects, if they do the same task, are generally named and capitalized the same way. This makes it less necessary to constantly refer to the documentation, which leads to faster coding.</p></blockquote><p>Agree.&#160; The inconsistencies in PHP names are well-documented.&#160;</p><blockquote><p><strong>3.</strong> Community maturity</p><p>The community is better able to give concise, coherent answers since the community is a little more learned. As it is generally not a first language the people in the community already have experience coding and helping others.</p></blockquote><p>Disagree.&#160; I can’t tell if he is in fact boasting that the Ruby community is in general smarter, but the PHP community includes some of the brightest and veteran software developers in the world.&#160; It is also one of the most diverse, in terms of skillset, and thus is also one of the <a
href="http://objo.com/2010/10/11/php-there-is-a-good-side/">most welcoming and open technology communities around</a>.&#160; Maybe he means that diversity is a disadvantage, which I also would disagree with.&#160; Anecdotally, the Ruby community is often perceived of as <a
href="http://www.flickr.com/photos/planetargon/127984254/">elitist</a> and prone to groupthink.&#160; I believe that these are qualities of a very <em>immature</em> community, one that has not healthily fragmented or penetrated the corporate world.&#160; The PHP community is older and <em>has </em>experienced this fragmentation, which seems to be exactly what the author is criticizing. Just wait, Ruby. Just wait.</p><blockquote><p><strong>4.</strong> Rails</p><p>Creating a web application complete with database is as easy as typing in a few simple commands. The web app framework community for PHP, on the other hand, is fragmented and far less organized.</p></blockquote><p>Basically agree.&#160; It is true that Ruby as a whole has embraced a single framework thus enjoying the advantages that have resulted.&#160; Would PHP have enjoyed the same benefits had it settled on a single framework early on?&#160; Impossible to know.&#160; I predict that over time, the Ruby web frameworks will become fragmented and less organized as well.</p><blockquote><p><strong>5.</strong> Objected Oriented Programming</p><p>Ruby was initially designed to be object-oriented. Robust, organized programs are easier to create with an object oriented language.</p></blockquote><p>Basically agree.&#160; It is of course possible to write very good object-oriented code in PHP, but Ruby provides less rope to hang yourself with.</p><blockquote><p><strong>6.</strong> ActiveRecord design</p><p>using Rails, it is possible to map database records/tables to objects, which makes creating and handling persistent data extremely easy.</p></blockquote><p>Basically agree.&#160; Like point #4 above, there are plenty of good <a
href="http://www.doctrine-project.org/">ActiveRecord libraries for PHP</a>, but having a single, agreed-upon ORM to go with your single, agreed-upon MVC framework lends many advantages.</p><blockquote><p><strong>7.</strong> Easier to install</p><p>Gem makes it extremely easy to download and install different frameworks and applications to use in your code. PHP, however, makes you find, download, install, and configure all extensions yourself.</p></blockquote><p>Disagree.&#160; This should not even be on this list.&#160; I see no real advantages of <code>gem</code> over <code><a
href="http://pear.php.net/">pear</a></code>.&#160; Furthermore, I have seen some really hairy gem problems involving paths and multiple installations.</p><blockquote><p><strong>8.</strong> MVC</p><p>The model view controller architecture is a common system that all software engineers use. Rails is designed around this concept, so it gives future maintainers of your project an advantage when trying to understand your code.</p></blockquote><p>Basically agree.&#160; See points #4 and #6 above.&#160; As I type this, points #4, #6, and #8 could be combined into a single item.</p><blockquote><p><strong>9.</strong> JVM support</p><p>Whenever there is a JVM installed, you can use JRuby to run your programs. You can also integrate your project into a Java application if you would like. This is especially useful if you are already writing a large application in Java, and are just looking for a scripting language to augment some functionality.</p></blockquote><p>Agree.&#160; I have no experience with either <a
href="http://jruby.org/">JRuby</a> or <a
href="http://www.caucho.com/resin-3.0/quercus/">Quercus</a>, but JRuby appears to have achieved more maturity and popularity faster than Quercus.</p><blockquote><p><strong>10.</strong> Formal namespaces</p><p>Organizing code is much easier when you can group classes into namespaces.</p></blockquote><p>Disagree.&#160; <a
href="http://php.net/manual/en/language.namespaces.php">PHP 5.3 fully supports namespaces</a>.&#160; Personally, I have always questioned the value of namespacing.&#160; It always seemed more confusing to have identically named entities in different namespaces than to just prefix them and call them different things – which is what you have to do in PHP 5.2.</p><blockquote><p><strong>11.</strong> Pre-installed on certain operating systems</p><p>It ships with OSX 10.5 (Leopard), so you can get started coding immediately.</p></blockquote><p>Disagree.&#160; It sounds like he is referring to local installations, and not deployed installations, but in either case I would disagree.&#160; OSX comes with PHP as well.&#160; And PHP comes installed on every Linux distro currently made, so I really don’t understand this one at all.&#160;&#160; If he is referring to deployed installations, PHP is still installed on more hosting environments than any other language, and it is easier to get running than any other language.&#160; <a
href="http://www.modrails.com/">Passenger</a> is slowly mitigating this situation, but PHP still is in front.</p><blockquote><p><strong>12.</strong> Interactive shell</p><p>It comes default with a robust interactive shell that makes it easy to experiment with code. Instead of typing out some code, saving it to your sever, opening up your internet browser, and navigating to your page, you can just open up the console and type.</p></blockquote><p>Agree.&#160; PHP has <code><a
href="http://www.php.net/manual/en/features.commandline.interactive.php">`php -a`</a></code>, but it is no where near as usable as IRB.</p><blockquote><p><strong>13.</strong> Maintainability</p><p>Less code (assuming the complexity is the same) means there is less to get confused about. Forcing MVC on you (through Rails) also helps developers maintain your code. Unit testing has also been tightly integrated from the beginning of the language, so it is more convenient to create/use unit tests for regression tests.</p></blockquote><p>Basically agree.&#160; I am now combining points #4, #6, #8, and #13.</p><blockquote><p><strong>14.</strong> Everything is an object</p><p>Not having primitives makes code easier to handle. Instead of making sure something is an object and then executing it’s methods, one can just execute the method.</p></blockquote><p>Agree.&#160; If you start treating everything as an object, your business model starts becoming cleaner.&#160; I’d much rather write <code>“hello world”.lower</code> than <code>strtolower(“hello world”)</code>.</p><p
align="center">:::</p><p>Right about now is when I might conclude with: “every situation is different and the proper solution depends on your particular requirements, blah, blah, blah.” I basically agree with that statement, but in my experience, it is missing the point.&#160;</p><p>In my experience, one can pretty much do anything with one platform that one can do with another.&#160; One (web) technology may be faster or easier, but in the end, it’s all just web.&#160; In my experience, most people are not equally strong in more than one platform.&#160; Most people are stronger in one language, even if it is because it is the language most recently used.&#160;</p><p>So back to the “every situation is different…” statement.&#160; The particular requirements are usually, how can I make the business money?&#160; Then, the proper solution becomes: by using the platform I know the best, and that is already running, formal namespaces be damned.</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2010/11/09/choosing-a-language/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Real Software Engineering</title><link>http://blog.straylightrun.net/2010/10/07/real-software-engineering/</link> <comments>http://blog.straylightrun.net/2010/10/07/real-software-engineering/#comments</comments> <pubDate>Thu, 07 Oct 2010 15:02:00 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Career]]></category> <category><![CDATA[Coding]]></category> <category><![CDATA[agile]]></category> <category><![CDATA[art]]></category> <category><![CDATA[craft]]></category> <category><![CDATA[engineering]]></category> <category><![CDATA[profession]]></category> <category><![CDATA[science]]></category> <category><![CDATA[software]]></category> <category><![CDATA[video]]></category> <category><![CDATA[waterfall]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2010/10/07/real-software-engineering/</guid> <description><![CDATA[So this talk given at JRubyConf 2010 has been setting user groups and Twitter afire.&#160; If you are a developer, I highly recommend you watch it. Real Software Engineering by @glv is amazing. Truly a foundational talk of our field. One of the best I&#8217;ve ever seen? #jrubyconfless than a minute ago via Tweetie for [...]]]></description> <content:encoded><![CDATA[<p>So this talk given at <a
href="http://jrubyconf.com/">JRubyConf 2010</a> has been setting user groups and Twitter afire.&#160; If you are a developer, I highly recommend you watch it.</p><p> <br
/><style type='text/css'>.bbpBox26193359683 {background:url(http://s.twimg.com/a/1285694546/images/themes/theme2/bg.gif) #C6E2EE;padding:20px;} p.bbpTweet{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} p.bbpTweet span.metadata{display:block;width:100%;clear:both;margin-top:8px;padding-top:12px;height:40px;border-top:1px solid #fff;border-top:1px solid #e6e6e6} p.bbpTweet span.metadata span.author{line-height:19px} p.bbpTweet span.metadata span.author img{float:left;margin:0 7px 0 0px;width:38px;height:38px} p.bbpTweet a:hover{text-decoration:underline}p.bbpTweet span.timestamp{font-size:12px;display:block}</style><div
class='bbpBox26193359683'><p
class='bbpTweet'>Real Software Engineering by @<a
class="tweet-url username" href="http://twitter.com/glv" rel="nofollow">glv</a> is amazing. Truly a foundational talk of our field. One of the best I&#8217;ve ever seen? <a
href="http://twitter.com/search?q=%23jrubyconf" title="#jrubyconf" class="tweet-url hashtag" rel="nofollow">#jrubyconf</a><span
class='timestamp'><a
title="Sat Oct 02 17:30:31 +0000 2010" href="http://twitter.com/coreyhaines/statuses/26193359683">less than a minute ago</a> via <a
href="http://twitter.com" rel="nofollow">Tweetie for Mac</a></span><span
class='metadata'><span
class='author'><a
href="http://twitter.com/coreyhaines"><img
src="http://a1.twimg.com/profile_images/70863601/3187276048_580e77883b-1_normal.jpg" /></a><strong><a
href="http://twitter.com/coreyhaines">Corey Haines</a></strong><br/>coreyhaines</span></span></p></div><p><p><em><a
href="http://confreaks.net/videos/282-lsrc2010-real-software-engineering">Real Software Engineering</a> talk presented at <a
href="http://www.lonestarrubyconf.com/">Lone Star Ruby Conference 2010</a>.</em></p><p> <embed
src="http://confreaks.net/media/player.swf" height="360" width="640" allowscriptaccess="always" allowfullscreen="true" flashvars="&#038;file=http%3A%2F%2Fconfreaks.net%2Fsystem%2Fassets%2Fdatas%2F24%2Foriginal%2Fglenn-vanderburg-smaller.mp4&#038;image=http%3A%2F%2Fconfreaks.net%2Fsystem%2Fvideos%2Fimages%2F282%2Fpreview%2Fglenn-vanderburg-smaller.mp4_snapshot_03.00_%5B2010.08.31_03.50.52%5D.jpg%3F1283251888&#038;plugins=viral-2&#038;viral.allowmenu=true" /></p><p></embed></p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2010/10/07/real-software-engineering/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>86% Of Writes Were For Statistics</title><link>http://blog.straylightrun.net/2010/09/30/86-of-writes-were-for-statistics/</link> <comments>http://blog.straylightrun.net/2010/09/30/86-of-writes-were-for-statistics/#comments</comments> <pubDate>Thu, 30 Sep 2010 20:19:00 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[mysql]]></category> <category><![CDATA[mysqltuner]]></category> <category><![CDATA[query cache]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2010/09/30/86-of-writes-were-for-statistics/</guid> <description><![CDATA[View counts, click counts, hit counts, traffic statistics… The need for analytics and reporting on web products is a must-have.&#160; Well, the easiest way to do that is to simply increment a database value each time.&#160; The problem is when those counts are coming in hundreds of times per second.&#160; Writes are the most expensive [...]]]></description> <content:encoded><![CDATA[<p>View counts, click counts, hit counts, traffic statistics… The need for analytics and reporting on web products is a must-have.&#160; Well, the easiest way to do that is to simply increment a database value each time.&#160; The problem is when those counts are coming in hundreds of times per second.&#160; Writes are the most expensive queries:</p><ol><li>Writes usually trigger updating an index.</li><li>If you’re using a MyISAM storage engine, the table-level locking can get out of hand.&#160;</li><li>Writes are not query-cacheable.</li></ol><p>After <a
href="http://blog.straylightrun.net/2010/09/29/mysql-slow-query-log-is-your-friend/">observing subpar write behavior</a>, I wanted to know just how many of our total writes were for updating statistics?</p><p>First, I ran <code><a
href="http://blog.mysqltuner.com/">mysqltuner</a></code>.</p><div
class="wp_syntax"><div
class="code"><pre class="sh" style="font-family:monospace;">% mysqltuner
...
[**] Reads / Writes: 93% / 7%
...
%</pre></div></div><p>So 7% of all queries were writes.&#160; That wasn’t bad.&#160; Then, I took the binary log of all DML statements for yesterday, starting at midnight.&#160; I figured 24 hours was a good sample.</p><div
class="wp_syntax"><div
class="code"><pre class="sh" style="font-family:monospace;">% mysqlbinlog  --start-date='2010-06-06 0' binary-log.000152 &gt; cow</pre></div></div><p>I grepped out DML lines, to get rid of the binary log stuff.</p><div
class="wp_syntax"><div
class="code"><pre class="sh" style="font-family:monospace;">% grep -i '^insert' cow &gt; cow2
% grep -i '^update' cow &gt;&gt; cow2</pre></div></div><p>I counted up lines that wrote to our stat tables.</p><div
class="wp_syntax"><div
class="code"><pre class="sh" style="font-family:monospace;">% wc -l cow2
24898 cow
% grep -i -c 'stat_' cow2
20880</pre></div></div><p>Doing the math: <code>20880 / 24898 = 0.86</code>. About 86% of all writes to our database were for statistics.&#160; Which wasn’t too surprising.&#160; Most web sites must store and log a lot of data to know where to improve and how users are using the site.</p><p>So what do we do?</p><p>That’s the subject of another post, but the short answer is that these writes can be batched somehow.&#160; Whether the queries are batched with some sort of write-through cache, or <a
href="http://activemq.apache.org/">job queues</a>, the database won’t suffer from constant write queries.</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2010/09/30/86-of-writes-were-for-statistics/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>MySQL Slow Query Log Is Your Friend</title><link>http://blog.straylightrun.net/2010/09/29/mysql-slow-query-log-is-your-friend/</link> <comments>http://blog.straylightrun.net/2010/09/29/mysql-slow-query-log-is-your-friend/#comments</comments> <pubDate>Wed, 29 Sep 2010 20:07:00 +0000</pubDate> <dc:creator>gerard</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[mysql]]></category> <category><![CDATA[query cache]]></category> <category><![CDATA[query log]]></category> <guid
isPermaLink="false">http://blog.straylightrun.net/2010/09/29/mysql-slow-query-log-is-your-friend/</guid> <description><![CDATA[The MySQL Slow Query Log is a required tool in the database administrator’s toolbox.&#160; It’s great for troubleshooting specific issues, but it’s also great for some rainy day application tuning. My slow query log is in /var/lib/mysqld/db-001-slow.log and records any queries that take longer than 10 seconds (the default value for long_query_time). I can get [...]]]></description> <content:encoded><![CDATA[<p>The <a
href="http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html">MySQL Slow Query Log</a> is a required tool in the database administrator’s toolbox.&#160; It’s great for troubleshooting specific issues, but it’s also great for some rainy day application tuning.</p><p>My slow query log is in <code>/var/lib/mysqld/db-001-slow.log</code> and records any queries that take longer than 10 seconds (the default value for <code>long_query_time)</code>. I can get information out of this log using <code>mysqldumpslow</code>.</p><p>Running <code>`mysqldumpslow db-001-slow.log`</code> prints out slow queries sorted by descending execution time. But that’s not useful to me, because any query can get delayed by a blip in the system.</p><p>I like running <code>`mysqldumpslow -s c db-001-slow.log`</code> which prints out the slow queries sorted by descending count of times that query occurred. Optimizing a query that takes 10 seconds to execute but occurs a dozen times every minute will be more beneficial than optimizing the query that takes 140 seconds to execute but rarely occurs.</p><p>The first time I tried this exercise, I revealed the following 3 types of slow queries (can’t remember the exact order now):</p><ol><li>Queries with lots of logic and joins returning infrequently-changing data.</li><li>Queries using the <code>curdate()</code> function, <a
href="http://blog.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/">which are not query cacheable</a>.</li><li>Queries to insert/update a stats table for content view counts.</li></ol><p>For #1, I used an <a
href="http://memcached.org/">in-memory cache</a> to cache the query results.&#160;&#160; For #2, I replaced the <code>curdate()</code> function with the PHP <code>date()</code> function everywhere I could find it.&#160; For #3, I noticed an extraneous index on the stats table, and indexes slow down inserts and updates, so I removed it.&#160; For more on handling these types of queries, see my <a
href="http://blog.straylightrun.net/2010/09/30/86-of-writes-were-for-statistics/">next post</a>.</p> ]]></content:encoded> <wfw:commentRss>http://blog.straylightrun.net/2010/09/29/mysql-slow-query-log-is-your-friend/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
