<?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>Carsonified &#187; Learn</title>
	<atom:link href="http://carsonified.com/blog/category/learn/feed/" rel="self" type="application/rss+xml" />
	<link>http://carsonified.com</link>
	<description></description>
	<lastBuildDate>Fri, 19 Mar 2010 15:14:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to Understand Your Users with Personas</title>
		<link>http://carsonified.com/blog/design/how-to-understand-your-users-with-personas/</link>
		<comments>http://carsonified.com/blog/design/how-to-understand-your-users-with-personas/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 16:00:04 +0000</pubDate>
		<dc:creator>Brad Colbow</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[UX]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3539</guid>
		<description><![CDATA[By <strong>Brad Colbow</strong><br />Personas are a powerful tool for helping you to better understand the needs of your users. In this comic, drawn exclusively for Think Vitamin, you&#8217;ll learn more about Personas and how they&#8217;ll revolutionize the way you design and build web sites.
Come hear Dan Cederholm, Jason Santa Maria, Joshua Davis, Bill Buxton, Daniel Burka, Elliot Jay [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdesign%2Fhow-to-understand-your-users-with-personas%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdesign%2Fhow-to-understand-your-users-with-personas%2F" height="61" width="51" /></a></div><p>Personas are a powerful tool for helping you to better understand the needs of your users. In this comic, drawn exclusively for Think Vitamin, you&#8217;ll learn more about Personas and how they&#8217;ll revolutionize the way you design and build web sites.</p>
<p><em>Come hear Dan Cederholm, Jason Santa Maria, Joshua Davis, Bill Buxton, Daniel Burka, Elliot Jay Stocks and more speak at <a href="http://events.carsonified.com/fowd/2009/nyc">The Future of Web Design NYC</a> on Nov 16 &#8211; 17th.</em></p>
<p><span id="more-3539"></span></p>
<p><img src="http://carsonified.com/wp-content/uploads/2009/10/personas_final_b.jpg" alt="Personas Comic" /></p>
<h3>More about Personas</h3>
<p>Putting Personas Under the Microscope<br />
<a href="http://www.cooper.com/journal/personas/">cooper.com/journal/personas</a></p>
<p>The Origin of Personas<br />
<a href="http://www.cooper.com/journal/2003/08/the_origin_of_personas.html">cooper.com/journal/2003/08/the_origin_of_personas.html</a></p>
<p>Getting from Research to Personas: Harnessing the Power of Data<br />
<a href="http://www.cooper.com/journal/2002/11/getting_from_research_to_perso.html">cooper.com/journal/2002/11/getting_from_research_to_perso.html</a></p>
<p>Personas and Goal-Directed Design: An Interview with Kim Goodwin<br />
<a href="http://www.uie.com/articles/goodwin_interview/">uie.com/articles/goodwin_interview</a></p>
<p>What&#8217;s your customer&#8217;s persona?<br />
<a href="http://www.usatoday.com/money/smallbusiness/columnist/abrams/2005-02-18-persona_x.htm">usatoday.com/money/smallbusiness/columnist/abrams/2005-02-18-persona_x.htm</a></p>
<h3>More from Indi Young:</h3>
<p>Book: Mental Models<br />
<a href="http://rosenfeldmedia.com/books/mental-models/">rosenfeldmedia.com/books/mental-models</a></p>
<p>Look at it Another Way<br />
<a href="http://www.alistapart.com/articles/lookatitanotherway/">alistapart.com/articles/lookatitanotherway</a></p>
<h3>More comics from Brad Colbow:</h3>
<p>Misunderstanding Markup<br />
<a href="http://www.smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip/">smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip</a></p>
<p>Alignment in design:<br />
<a href="http://sixrevisions.com/web_design/the-brads-alignment-in-design/">sixrevisions.com/web_design/the-brads-alignment-in-design</a></p>
<p>The Brads, a weekly web comic<br />
<a href="http://bradcolbow.com">bradcolbow.com</a></p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3539&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/design/how-to-understand-your-users-with-personas/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>The Future of HTML 5</title>
		<link>http://carsonified.com/blog/web-apps/the-future-of-html-5/</link>
		<comments>http://carsonified.com/blog/web-apps/the-future-of-html-5/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 12:10:49 +0000</pubDate>
		<dc:creator>Bruce Lawson</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Web Apps]]></category>
		<category><![CDATA[fowa-london-09]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3521</guid>
		<description><![CDATA[By <strong>Bruce Lawson</strong><br />At FOWA London 2009 Bruce Lawson gave an introduction to HTML 5 and how it might be used in the future.
The HTML 5 spec was originally called &#8220;Web Applications 1.0&#8243;. Most of the attention has been on the new markup elements, but in his talk he takes a further look at the applications side of [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fweb-apps%2Fthe-future-of-html-5%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fweb-apps%2Fthe-future-of-html-5%2F" height="61" width="51" /></a></div><p>At <a href="http://events.carsonified.com/fowa/2009/london">FOWA London 2009</a> Bruce Lawson gave an introduction to HTML 5 and how it might be used in the future.</p>
<p>The HTML 5 spec was originally called &#8220;Web Applications 1.0&#8243;. Most of the attention has been on the new markup elements, but in his talk he takes a further look at the applications side of the spec, covering:</p>
<ol>
<li> Dynamic images and graphs with canvas</li>
<li> Eliminating much forms validation with webforms 2.0</li>
<li> Local storage automagically saving your data</li>
<li> Geolocation</li>
<li> Building toolbars and menus.</li>
</ol>
<p><em>Editor&#8217;s Note: We&#8217;ll be covering &#8220;How HTML 5 is Going to Completely Change your Web App&#8221; at <a href="http://events.carsonified.com/fowa/2010/miami">The Future of Web Apps in Miami</a>.</em></p>
<p><span id="more-3521"></span></p>
<p>You can <a href="http://carsonified.com/blog/web-apps/the-future-of-html-5#thevideo">jump straight to the video</a>, <a href="http://carsonified.com/blog/web-apps/the-future-of-html-5#theslides">view the slides</a>, <a href="http://joeloverton.com/html5">read the transcript</a> (thanks <a href="http://twitter.com/joeloverton">@joeloverton</a> for doing this!), or check out the resources he demos in the talk:</p>
<ul>
<li><a href="http://9elements.com/io/projects/html5/canvas/">Eye-candy canvas</a></li>
<li><a href="http://www.benjoffe.com/code/demos/canvascape/">canvas first-person shooter</a></li>
<li><a href="http://htmlfive.appspot.com/static/gifter.html">canvas first-person gifter</a></li>
<li><a href="http://excanvas.sourceforge.net/">the excanvas library to port canvas to Internet Explorer</a></li>
<li><a href="http://www.filamentgroup.com/lab/jquery_visualize_plugin_accessible_charts_graphs_from_tables_html5_canvas/">Filament Group&#8217;s jQuerty plugin using canvas for graphing data tables</a></li>
<li><a href="http://raphaeljs.com/">Raphaël JavaScript Library to make <abbr>SVG</abbr> that also works in Internet Explorer</a></li>
<li> <a href="http://code.google.com/p/svgweb/">SVG Web is a JavaScript library which provides SVG support on Internet Explorer</a> (Alpha code: not ready for production)</li>
<li> <a href="http://people.opera.com/brucel/demo/forms/html5-forms-advanced-demo.html">My <abbr>HTML</abbr>5 forms demo, including range, date, placeholder, regex validation</a> (Try in Opera and Chrome)</li>
<li> <a href="http://www.modernizr.com">modernizr</a> &#8211; A small <abbr>HTML</abbr>5 capability detection library</li>
<li> <a href="http://www.html5demos.com/"><abbr>HTML</abbr>5demos.com</a> &#8211; Remy Sharp&#8217;s demos of geolocation, offline storage and web database and many others</li>
<li><a href="http://people.opera.com/brucel/demo/video-demos.html">Video demos</a></li>
</ul>
<p>Other useful resources:</p>
<ul>
<li> <a href="http://svgopen.org/2009/papers/54-SVG_vs_Canvas_on_Trivial_Drawing_Application">SVG vs. Canvas on Trivial Drawing Application</a>: a comparison of canvas and <abbr>SVG</abbr></li>
<li><a href="http://dev.w3.org/html5/spec-author-view/"><abbr>HTML</abbr>5 Authors spec</a></li>
<li>A video of <a href="http://blip.tv/file/2299313">Dean Edwards demoing his unreleased JavaScript library that detects and plugs the holes in current browsers&#8217; <abbr>HTML</abbr>5 support</a></li>
</ul>
<p>There are some great beginner canvast tutorials on the Opera Developer:</p>
<ol>
<li><a href="http://dev.opera.com/articles/view/html-5-canvas-the-basics/">HTML 5 canvas &#8211; the basics</a></li>
<li><a href="http://dev.opera.com/articles/view/html5-canvas-painting/">Creating an HTML 5 canvas painting application</a></li>
<li><a href="http://dev.opera.com/articles/view/creating-pseudo-3d-games-with-html-5-can-1/">Creating pseudo 3D games with HTML 5 canvas and raycasting</a></li>
<li><a href="http://dev.opera.com/articles/view/3d-games-with-canvas-and-raycasting-part/">Creating pseudo 3D games with HTML 5 canvas and raycasting: Part 2</a></li>
</ol>
<h3 id="thevideo">The video</h3>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="471" height="259" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=6985053&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=eb6f00&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="471" height="259" src="http://vimeo.com/moogaloop.swf?clip_id=6985053&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=eb6f00&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Full transcription available at <a href="http://joeloverton.com/html5">joeloverton.com/html5</a>. We&#8217;d like to say a HUGE thank you to <a href="http://twitter.com/joeloverton">@joeloverton</a> for doing this transcription!</p>
<h3 id="theslides">The slides</h3>
<p><object style="margin:0px" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=bruce-lawson-opera-fowa-html5-091013075453-phpapp02&amp;stripped_title=the-future-of-html-5-by-bruce-lawson" /><param name="allowfullscreen" value="true" /><embed style="margin:0px" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=bruce-lawson-opera-fowa-html5-091013075453-phpapp02&amp;stripped_title=the-future-of-html-5-by-bruce-lawson" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3521&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/web-apps/the-future-of-html-5/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>9 Ways to Take Your Site from One to One Million Users</title>
		<link>http://carsonified.com/blog/web-apps/9-ways-to-take-your-site-from-one-to-one-million-users/</link>
		<comments>http://carsonified.com/blog/web-apps/9-ways-to-take-your-site-from-one-to-one-million-users/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 18:25:39 +0000</pubDate>
		<dc:creator>Kevin Rose</dc:creator>
				<category><![CDATA[Learn]]></category>
		<category><![CDATA[Web Apps]]></category>
		<category><![CDATA[fowa-london-09]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3449</guid>
		<description><![CDATA[By <strong>Kevin Rose</strong><br />In this video from The Future of Web Apps London (FOWA), Kevin Rose, founder of Digg, WeFollow and Revision3, shares 9 things he did to increase his users to 1,000,000 and beyond.
Here&#8217;s a quick bullet-point summary. You can watch the video, view the presentation slides or download the audio.
If you enjoy this article, you&#8217;ll love [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fweb-apps%2F9-ways-to-take-your-site-from-one-to-one-million-users%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fweb-apps%2F9-ways-to-take-your-site-from-one-to-one-million-users%2F" height="61" width="51" /></a></div><p>In this video from The Future of Web Apps London (FOWA), Kevin Rose, founder of Digg, WeFollow and Revision3, shares 9 things he did to increase his users to 1,000,000 and beyond.</p>
<p>Here&#8217;s a quick bullet-point summary. You can <a href="http://carsonified.com/blog/web-apps/9-ways-to-take-your-site-from-one-to-one-million-users#thevideo">watch the video</a>, <a href="http://www.slideshare.net/carsonified/taking-your-site-from-one-to-one-million-users-by-kevin-rose">view the presentation slides</a> or <a href="http://media.libsyn.com/media/carsonified/Kevin_Rose_-_FOWA_London_2009.mp3">download the audio</a>.</p>
<p><em>If you enjoy this article, you&#8217;ll love <a href="http://events.carsonified.com/fowa/2010/miami">The Future of Web Apps Miami</a>. Speakers include: Twitter, Mint.com, Gary Vaynerchuk, jQuery, Reddit and more. <a href="http://www.amiando.com/fowamiami2010.html">Buy your ticket now</a>.</em></p>
<p><span id="more-3449"></span></p>
<h3>#1. Ego</h3>
<ol>
<li>Ask yourself: Does this feature increase the users self-worth or stoke the ego?</li>
<li>If a user is contributing to my system, what emotional rewards do they walk away with? What (visible) rewards will they receive?</li>
</ol>
<h3>#2. Simplicity</h3>
<ol>
<li>Stop over building features</li>
<li>Pick 2-3 things to focus on</li>
<li>Ask yourself: Is there anything I can take out of this feature?</li>
</ol>
<h3>#3. Build &amp; Release</h3>
<ol>
<li>Stop thinking you understand your users</li>
<li>Learn from what they’re actually doing on your site, not what you think they’ll do</li>
<li>Decide on what you’re going to build&#8230; and build it (avoid analysis paralysis)</li>
<li>Build, release, iterate, and repeat</li>
</ol>
<h3>#4. Hack The Press</h3>
<ol>
<li>Invite only system (Pownce, Digg v3)</li>
<li>Talk to the junior bloggers</li>
<li>Attend parties for events you can’t afford &#8211; network w/influencers, bring a demo</li>
</ol>
<h3>#5. Connect with your community</h3>
<ol>
<li>Start a podcast (it’s OK if not everyone listens)</li>
<li>Throw a launch party, then yearly/quarterly  events &#8211; invite the press/influencers personally &#8211; don’t tell the bar</li>
<li>Engage w/the community, be an active participant your own ecosystem</li>
</ol>
<h3>#6. Advisors</h3>
<ol>
<li>What technical problems are you going to have?</li>
<li>Advisors can be helpful in a whole slew of areas (marketing/hiring/bizdev)</li>
<li>Stock compensation, typically not a board seat, solid advisors help during fund raising</li>
</ol>
<h3>#7. Leverage your userbase to spread the word</h3>
<h3>#8. Does your product provide value for 3rd party sites?</h3>
<h3>#9. Analyze your traffic</h3>
<ol>
<li>Install Google analytics</li>
<li>Entrance sources (search?)</li>
<li>Paths through site</li>
<li>Top exit pages</li>
</ol>
<h3 id="thevideo">The Video</h3>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="471" height="259" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=6905398&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=eb6f00&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="471" height="259" src="http://vimeo.com/moogaloop.swf?clip_id=6905398&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=eb6f00&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3449&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/web-apps/9-ways-to-take-your-site-from-one-to-one-million-users/feed/</wfw:commentRss>
		<slash:comments>54</slash:comments>
<enclosure url="http://media.libsyn.com/media/carsonified/Kevin_Rose_-_FOWA_London_2009.mp3" length="27901168" type="audio/mpeg" />
		</item>
		<item>
		<title>Introducing Atlas: A Visual Development Tool for Creating Web Apps</title>
		<link>http://carsonified.com/blog/web-apps/introducing-atlas-a-visual-development-tool-for-creating-web-apps/</link>
		<comments>http://carsonified.com/blog/web-apps/introducing-atlas-a-visual-development-tool-for-creating-web-apps/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 05:06:32 +0000</pubDate>
		<dc:creator>Francisco Tolmasky</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Web Apps]]></category>
		<category><![CDATA[fowa-london-09]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3464</guid>
		<description><![CDATA[By <strong>Francisco Tolmasky</strong><br />In this video from FOWA London 2009, Francisco Tolmasky will demo Atlas, a new visual tool for building web apps and desktop apps. It will blow your mind and change what you thought was possible with web apps. This is new footage that has not been shown to the public ever before.
Editor&#8217;s Note: Only eight [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fweb-apps%2Fintroducing-atlas-a-visual-development-tool-for-creating-web-apps%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fweb-apps%2Fintroducing-atlas-a-visual-development-tool-for-creating-web-apps%2F" height="61" width="51" /></a></div><p>In this video from FOWA London 2009, Francisco Tolmasky will demo <a href="http://280atlas.com/">Atlas</a>, a new visual tool for building web apps and desktop apps. It will blow your mind and change what you thought was possible with web apps. This is new footage that has not been shown to the public ever before.</p>
<p><em>Editor&#8217;s Note: <strong>Only eight hours till we launch FOWA Miami 2010</strong>! There&#8217;s only 20 Super Early Bird tickets at 47% off, so be quick (only 440 seats total, so the show will definitely sell out early). Speakers include: Twitter, Reddit, Mint.com, jQuery, Palm Pre, FreshBooks, Opera and PayPal. Keep an eye on <a href="http://events.carsonified.com">events.carsonified.com</a> for the launch at 9am EST.</em></p>
<p><span id="more-3464"></span></p>
<p><object width="471" height="259"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=6930037&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=eb6f00&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=6930037&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=eb6f00&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="471" height="259"></embed></object></p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3464&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/web-apps/introducing-atlas-a-visual-development-tool-for-creating-web-apps/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>OpenSocial Tutorial</title>
		<link>http://carsonified.com/blog/dev/opensocial-tutorial/</link>
		<comments>http://carsonified.com/blog/dev/opensocial-tutorial/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 16:42:07 +0000</pubDate>
		<dc:creator>Tobias Günther</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[OpenSocial]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3420</guid>
		<description><![CDATA[By <strong>Tobias Günther</strong><br />Want to reach more than 500 million users with your social app? OpenSocial is the key. The OpenSocial standard will allow you to build apps that work across a number of massive social networks, including MySpace, Orkut, Ning, hi5 and LinkedIn (complete list).
OpenSocial defines an API for developing social apps and was designed in cooperation [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fopensocial-tutorial%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fopensocial-tutorial%2F" height="61" width="51" /></a></div><p>Want to reach more than 500 million users with your social app? OpenSocial is the key. The OpenSocial standard will allow you to build apps that work across a number of massive social networks, including MySpace, Orkut, Ning, hi5 and LinkedIn (complete <a href="http://wiki.opensocial.org/index.php?title=Main_Page#Container_Information" target="_blank">list</a>).</p>
<p>OpenSocial defines an API for developing social apps and was designed in cooperation with multiple social networks right from the start. Amongst many others, companies like Google, Yahoo!, LinkedIn and MySpace support the interface.</p>
<p><em>Editor&#8217;s Note: Looks like <a href="http://events.carsonified.com/fowa/2009/london?utm_source=TV&#038;utm_medium=Text%2Blink&#038;utm_campaign=OpenSocial%2BTutorial">The Future of Web Apps</a> will definitely sell out. Speakers: Twitter, Facebook, Google, Six Apart, digg / Kevin Rose, Mozilla, Dustin Diaz and more.</em></p>
<p><span id="more-3420"></span></p>
<h3>OpenSocial Tutorial</h3>
<p>I&#8217;m going to walk you through building a simple chat application using the OpenSocial API. You can download the complete code for the application <a href="http://www.puremedia-online.com/fileadmin/user_upload/tutorials_manuals/opensocial_chat_tutorial_thinkvitamin.zip">here</a>.</p>
<p>If you want to follow our example in code, a few smaller preparations are necessary. These are necessary mainly because of the fact that OpenSocial development only really makes sense inside of a real social platform which provides the API. Isolated on your home desktop it makes little sense because the basic platform is only available online, from the inside (embedded into) the platform.</p>
<p>For our example, you need a free Orkut account (a valid Google account is also sufficient) and access to the Orkut developer sandbox. The setup of your Orkut account including access to the developer sandbox is described in the document <a href="http://code.google.com/intl/de/apis/orkut/articles/tutorial/tutorial.htm" target="_blank">OpenSocial-Tutorial for Orkut</a> in the segment &#8220;Running your first Gadget&#8221;.</p>
<p>Because chatting without friends isn&#8217;t very exciting, it&#8217;s vital that you also add a few friends to your Orkut account. If you can&#8217;t get any of your colleagues to also register for the Orkut sandbox, you can simply create a second Google/Orkut account, open that one in another browser, add yourself (the other Orkut account) as a friend and then  install the app as well.</p>
<p>If you want to program your own Gadget and also make changes to the example code provided, you  need a little webspace, including PHP and a MySQL. The other preparations for this are documented in the Readme file in the download archive.</p>
<h3>Google Gadgets as a Foundation</h3>
<p>The basis for an OpenSocial application is a so-called <a href="http://code.google.com/intl/de/apis/gadgets/" target="_blank">Google Gadget</a>, which could be familiar already to some developers from experiences with iGoogle, e.g.</p>
<p>A Gadget is an XML document and is merely the frame for an OpenSocial app.<br />
An exemplary Gadget definition could look as follows:</p>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Module&gt;
  &lt;ModulePrefs title="Chat Tutorial"&gt;
      &lt;Require feature="opensocial-0.8" /&gt;
  &lt;/ModulePrefs&gt;
  &lt;Content type="html"&gt;
      &lt;![CDATA[
         // here comes our application code...
      ]]&gt;
  &lt;/Content&gt;
&lt;/Module&gt;</code></pre>
<p>The real application code is defined within the &lt;Content&gt; node of the Gadget and consist of HTML and JavaScript (while the embedding of Flash or Silverlight objects is possible too). All following JavaScript code snippets in this article belong inside of this &lt;Content&gt; node.</p>
<h3>Initialize the App</h3>
<p>Because we work with JavaScript within our Gadgets, at first we should wait until the page has completely loaded to be able to initialize our application cleanly. From Javascript frameworks like jQuery or Prototype you&#8217;re probably already used to getting informed as soon as the DOM is ready and we can begin with the initialization. Google&#8217;s Gadget-API also has such a helper function:</p>
<pre><code>gadgets.util.registerOnLoadHandler(function(){
    load_friends();
});</code></pre>
<h3>Querying for Data in OpenSocial</h3>
<p>An important part of our chat application is a simple list of our friends. To find out who our friends are (and how many we have) we ask our social network container (which is Orkut in our example). The corresponding JavaScript function &#8220;load_friends&#8221;, which we called on initialization, looks like this:</p>
<pre><code>function load_friends(){
    var req = opensocial.newDataRequest();
    req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), 'viewer');
    var friends = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" });
    req.add(req.newFetchPeopleRequest(friends, {}), 'viewer_friends');
    req.send(on_load_friends);
}</code></pre>
<p>From this example we see how data queries work in OpenSocial:</p>
<p>
In the first line we create a &#8220;DataRequest&#8221; object. All requests which we would like to have answered are appended to this object subsequently; in our example we first add a query for the profile data of the &#8220;Viewer&#8221; and then a query for his friends by calling req.add().</p>
<p>Because we work exclusively with JavaScript and HTML here, data queries are also carried out asynchronously through JavaScript (using AJAX).</p>
<p>
It&#8217;s only in the last line of our example that the request is really sent through req.send(). It&#8217;s worth noting that, with this concept of querying, we can immediately take care of several data queries in only one request &#8211; instead of needing several AJAX requests and generating traffic and latency several times. Google calls this procedure &#8220;batch requesting&#8221;.</p>
<p>At the same time, looking at that code snippet, you can clearly see what it&#8217;s all about in OpenSocial: it&#8217;s about &#8220;people data&#8221; and the relations of the people to each other. Two types of persons are the most interesting, which is why the API defines them as constants:</p>
<p>One of them is the &#8220;VIEWER&#8221;. The Viewer is the (logged in) user who&#8217;s looking at the profile page on which our application is installed. The other one is the &#8220;OWNER&#8221;, which is the owner of the profile page on which the Gadget is installed. It is perfectly possible that the Owner and the Viewer at times are the same user &#8211; when the owner is looking at his own profile page, using the application.</p>
<p>
In addition to Viewer and Owner, it is also possible to request data about other users by their user ID.</p>
<p>As we sent off our requests we had given an additional parameter to the method req.send(). This was the reference to the function &#8220;on_load_friends&#8221; which is used as a callback and is automatically called as soon as our request was answered and returned data. Therefore, we can access the results of our query &#8211; the person data we asked for &#8211; inside of the function &#8220;on_load_friends&#8221;:</p>
<pre><code>function on_load_friends(data) {
    var viewer = data.get('viewer').getData();
    var friends = data.get('viewer_friends').getData();
    ...
}</code></pre>
<p>Accessing our data through the method &#8220;get()&#8221; is necessary because of the &#8220;batch requesting&#8221;. While putting together the query, we had provided the strings &#8216;viewer&#8217; respectively &#8216;viewer_friends&#8217; as a last parameter. This was necessary because we wanted to request multiple data packages in one go &#8211; and of course we want to be able to distinguish them again at the end. Through data.get (&#8216;viewer&#8217;).getData () we get the return values which we had named &#8216;viewer&#8217; when we put together the request.</p>
<p>Now in the next step we want to show our friends in a list:</p>
<pre><code>friends.each(function(friend) {
    friends_html += '&lt;div class="friend_name"&gt; '+ friend.getDisplayName()+ '&lt;/div&gt;';
});</code></pre>
<p>Those of you who have already worked with Ruby or the JavaScript framework Prototype will probably know the &#8220;each&#8221; notation. The OpenSocial-API provides this function, too. We use it here to iterate through the records of our friends.</p>
<p>By calling &#8220;getDisplayName()&#8221; on each of our friends records we use a special function of OpenSocial.</p>
<p>
Most data fields are specific for a certain platform. This means e.g. that a field called &#8220;hobbies&#8221; that exists on MySpace might not exist in another container like Orkut at all. To at least be able to show a display name &#8211; in any case, and on any platform &#8211; a sensible return value from getDisplayName is guaranteed by the API.</p>
<p>
In other cases we should be more careful by explicitly checking if a certain field that we&#8217;re trying to access really exists:</p>
<pre><code>opensocial.getEnvironment().supportsField(opensocial.Environment.ObjectType.PERSON, opensocial.Person.Field.ID);</code></pre>
<p>With this line of code, we can check if there&#8217;s a field called &#8216;id&#8217; for objects of type &#8216;person&#8217;. As soon as we know that our field of choice really exists, we can access it through &#8220;getField()&#8221;:</p>
<pre><code>friend.getField(opensocial.Person.Field.ID);</code></pre>
<p>A few specialities still have to be considered when sending a chat message:</p>
<pre><code>function send_message(message, user_to, user_from){
    var post_data = { action: 'save_message', message: message, to_user: user_to, from_user: user_from};
    post_data = gadgets.io.encodeValues(post_data);
    var params = {};
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
    params[gadgets.io.RequestParameters.POST_DATA] = post_data;
    gadgets.io.makeRequest('http://www.example.com/message.php', function(){}, params);
}</code></pre>
<p>Our self-defined method &#8220;send_message()&#8221; is used to send an entered message via AJAX to a remote server. This remote server then saves the message in a database until it is picked up by it&#8217;s receiver.</p>
<p>
Inside of this function, the Gadgets-API is used heavily. This is necessary because it&#8217;s not easily possible for security reasons to send a request to an other than the origin server with AJAX. Here the Gadgets-API steps in, which makes this possible through &#8220;gadgets.io.makeRequest&#8221;.</p>
<h3>Other Possibilities</h3>
<p>The OpenSocial-API offers some more possibilities. With the help of the Activities-API you can, for example, read or write activity messages for a user. Therefore, an application would be able to read or write activity messages like &#8220;Mike has a new profile photo&#8221; or &#8220;Martin and Linda are friends, now&#8221;.</p>
<p>A so-called &#8220;Lifecycle event&#8221; can help developers gear into important points in the life cycle of an application. As a developer, you can for example, be informed when the deinstallation of a Gadget happens and take actions accordingly (by deleting old database entries, for example).</p>
<p>Another area of the API deals with data persistence. This functionality is exciting because OpenSocial apps &#8211; being &#8220;just a frontend&#8221; at first hand &#8211; come without their own backends and therefore have no database by default. Every social network can decide for itself to which extent it allows applications to persist data for a viewer.</p>
<p>The concept of &#8220;Views&#8221; is also an interesting part of OpenSocial development: An OpenSocial-Gadget can have different views. This depends on where the Gadget was integrated, respectively in which view a user is at this specificmoment. The current view can be requested at runtime so that, e.g., different functionalities can be offered depending on the currently active view of the Gadget.</p>
<p>
Basically four different view types are defined in OpenSocial: The &#8220;Profile&#8221; view is active when it is viewed on the profile page of the user. The &#8220;Home&#8221; view is active when a Gadget is viewed on the personal homepage of the user (on which the above mentioned viewer and owner constants are always identical, because only the account owner has access to his personal homepage). The &#8220;Canvas&#8221; view is a view in which the Gadget is more or less alone on the page and therefore has a lot of space available. Finally, the &#8220;Preview&#8221; view has limited accesses and is intended for demo purposes.</p>
<h3>Publishing your SocialApp</h3>
<p>The development of an OpenSocial application always begins in a sandboxed developer environment where you can work on your application without interruptions. During this time, however, the app is only accessible to the developer himself (or other developers) &#8211; but not publicly to normal users.</p>
<p>
Then &#8211; after some time of development and testing &#8211; when your SocialApp has a sufficient level of maturity and is ready to enrich the world, you can submit it to the respective social network to be checked and (hopefully) approved.</p>
<p>
Though the submission process is a little different in every social network (as an example you find <a href="http://sandbox.orkut.com/Main#AppDirectorySubmit.aspx" target="_blank">Orkut&#8217;s application form here</a>), it always serves the same purpose: to put your submitted app through their paces.</p>
<p>
If then, after several days or weeks, your application was found to be nice enough, it is included into the platform&#8217;s list of applications &#8211; and can be installed by all users of the platform.</p>
<h3>Summary</h3>
<p>Google&#8217;s OpenSocial-API only really offers the functionality that Facebook developers are already accustomed to. However, with OpenSocial, you can reach a wider and larger audience of 500 million people.</p>
<p>In day-to-day development, in spite of the wholehearted promise &#8220;Many sites, one API&#8221;, caution is advised: some of the networks don&#8217;t implement the complete specification or take awhile to implement updates to their APIs. Sometimes some minor differences in the API implementation force you to adapt to special situations (hi5, for example, requires the Gadget scaffolding to be a little bit more detailed).</p>
<p>The result so far that OpenSocial can present, however, looks good: excellent <a href="http://code.google.com/intl/de/apis/opensocial/" target="_blank">documentation</a>, more than 30 <a href="http://wiki.opensocial.org/index.php?title=Main_Page#Container_Information" target="_blank">involved social networks</a> all over the world, and more than half a billion users.</p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3420&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/dev/opensocial-tutorial/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>How to Debug in PHP</title>
		<link>http://carsonified.com/blog/dev/how-to-debug-in-php/</link>
		<comments>http://carsonified.com/blog/dev/how-to-debug-in-php/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 07:00:31 +0000</pubDate>
		<dc:creator>Kieran Masterton</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3037</guid>
		<description><![CDATA[By <strong>Kieran Masterton</strong><br />Nobody enjoys the process of debugging their code. If you want to build killer web apps though, it&#8217;s vital that you understand the process thoroughly.
This article breaks down the fundamentals of debugging in PHP, helps you understand PHP&#8217;s error messages and introduces you to some useful tools to help make the process a little less [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-debug-in-php%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-debug-in-php%2F" height="61" width="51" /></a></div><p>Nobody enjoys the process of debugging their code. If you want to build killer web apps though, it&#8217;s vital that you understand the process thoroughly.</p>
<p>This article breaks down the fundamentals of debugging in PHP, helps you understand PHP&#8217;s error messages and introduces you to some useful tools to help make the process a little less painful.</p>
<p><em>Editor&#8217;s Note: We&#8217;ll be running workshops like &#8220;How to Build a Web App from A-Z&#8221; at <a href="http://events.carsonified.com/fowa/2009/london/workshops#workshop_53?utm_source=TV&#038;utm_medium=Text%2Blink&#038;utm_campaign=How%2Bto%20Debug%20in%20PHP">The Future of Web Apps London</a>.</em></p>
<p><span id="more-3037"></span></p>
<h3>Doing your Ground Work</h3>
<p>It is important that you configure PHP correctly and write your code in such a way that it produces meaningful errors at the right time. For example, it is generally good practice to turn on a verbose level of error reporting on your development platform. This probably isn&#8217;t such a great idea, however, on your production server(s). In a live environment you neither want to confuse a genuine user or give malicious users too much information about the inner-workings of your site.</p>
<p>So, with that in mind lets talk about the all too common &#8220;I&#8217;m getting no error message&#8221; issue. This is normally caused by a syntax error on a platform where the developer has not done their ground work properly. First, you should turn display_errors on. This can be done either in your php.ini file or at the head of your code like this:</p>
<p><code>&lt;?php<br />
ini_set('display_errors', 'On');</code></p>
<p><em>Tip: In these code examples I omit the closing (?&gt;) PHP tag. It is <a href="http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html#coding-standard.php-file-formatting.general" title="Zend Coding Standards">generally considered good practice</a> to do so in files which contain only PHP code in order to avoid accidental injection of white space and the all too common &#8220;headers already sent&#8221; error.</em></p>
<p>Next, you will need to set an error reporting level. As default PHP 4 and 5 do not show PHP notices which can be important in debugging your code (more on that shortly). Notices are generated by PHP whether they are displayed or not, so deploying code with twenty notices being generated has an impact upon the overhead of your site. So, to ensure notices are displayed, set your error reporting level either in your php.ini or amend your runtime code to look like this:</p>
<p><code>&lt;?php<br />
ini_set('display_errors', 'On');<br />
error_reporting(E_ALL);</code></p>
<p><em>Tip: E_ALL is a constant so don&#8217;t make the mistake of enclosing it in quotation marks.</em></p>
<p>With PHP 5 it&#8217;s also a good idea to turn on the E_STRICT level of error reporting. E_STRICT is useful for ensuring you&#8217;re coding using the best possible standards. For example E_STRICT helps by warning you that you&#8217;re using a deprecated function. Here&#8217;s how to enable it at runtime:</p>
<p><code>&lt;?php<br />
ini_set('display_errors', 'On');<br />
error_reporting(E_ALL | E_STRICT);</code></p>
<p>It is also worth mentioning that on your development platform it is often a good idea to make these changes in your php.ini file rather than at the runtime. This is because if you experience a syntax error with these options set in your code and not in the php.ini you may, depending on your set up, be presented with a blank page. Likewise, it is worth noting that if you&#8217;re setting these values in your code, a conditional statement might be a good idea to avoid these settings accidentally being deployed to a live environment.</p>
<h3>What Type of Error am I Looking at?</h3>
<p>As with most languages, PHP&#8217;s errors may appear somewhat esoteric, but there are in fact only four key types of error that you need to remember:</p>
<p><strong>1. Syntax Errors</strong></p>
<p>Syntactical errors or parse errors are generally caused by a typo in your code. For example a missing semicolon, quotation mark, brace or parentheses. When you encounter a syntax error you will receive an error similar to this:</p>
<p><code><strong>Parse error:</strong> syntax error, unexpected T_ECHO in /Document/Root/example.php on line 6</code></p>
<p>In this instance it is important that you check the line above the line quoted in the error (in this case line 5) because while PHP has encountered something unexpected on line 6, it is common that it is a typo on the line above causing the error. Here&#8217;s an example:</p>
<p><code>&lt;?php<br />
ini_set('display_errors', 'On');<br />
error_reporting(E_ALL);<br/><br/><br />
$sSiteName = "Think Vitamin"<br />
echo $sSiteName;</code></p>
<p>In this example I have omitted the semi-colon from line 5, however, PHP has reported an error occurred on line 6. Looking one line above you can spot and rectify the problem.</p>
<p><em>Tip: In this example I am using <a href="http://en.wikipedia.org/wiki/Hungarian_notation" title="Wikipedia entry for Hungarian Notation">Hungarian Notation</a>. Adopting this coding standard can aid with debugging code while working collaboratively or on a piece of code you wrote some time ago. The leading letter denoting the variable type means that determining a variable type is very quick and simple. This can aid in spotting irregularities which can also help highlight any potential logic errors.</em></p>
<p><strong>2. Warnings</strong></p>
<p>Warnings aren&#8217;t deal breakers like syntax errors. PHP can cope with a warning, however, it knows that you probably made a mistake somewhere and is notifying you about it. Warnings often appear for the following reasons:</p>
<ol>
<li>Headers already sent. Try checking for white space at the head of your code or in files you&#8217;re including.</li>
<li>You&#8217;re passing an incorrect number of parameters to a function.</li>
<li>Incorrect path names when including files.</li>
</ol>
<p><strong>3. Notices</strong></p>
<p>Notices aren&#8217;t going to halt the execution of your code either, but they can be very important in tracking down a pesky bug. Often you&#8217;ll find that code that&#8217;s working perfectly happily in a production environment starts throwing out notices when you set error_reporting to E_ALL.</p>
<p>A common notice you&#8217;ll encounter during development is:</p>
<p><code>><strong>Notice:</strong> Undefined index: FullName in /Document/Root/views/userdetails.phtml on line 55</code></p>
<p>This information can be extremely useful in debugging your application. Say you&#8217;ve done a simple database query and pulled a row of user data from a table. For presentation in your view you&#8217;ve assigned the details to an array called $aUserDetails. However, when you echo $aUserDetails['FirstName'] on line 55 there&#8217;s no output and PHP throws the notice above. In this instance the notice you receive can really help.</p>
<p>PHP has helpfully told us that the FirstName key is undefined so we know that this isn&#8217;t a case of the database record being NULL. However, perhaps we should check our SQL statement to ensure we&#8217;ve actually retrieved the user&#8217;s first name from the database. In this case the notice has helped us rule out a potential issue which has in turn steered us towards the likely source of our problem. Without the notice our likely first stop would have been the database record, followed by tracing back through our logic to eventually find our omission in the SQL.</p>
<p><strong>4. Fatal Errors</strong></p>
<p>Fatal Errors sound the most painful of the four but are in fact often the easiest to resolve. What it means, in short, is that PHP understands what you&#8217;ve asked it to do but can&#8217;t carry out the request. Your syntax is correct, you&#8217;re speaking its language but PHP doesn&#8217;t have what it needs to comply. The most common fatal error is an undefined class or function and the error generated normally points straight to the root of the problem:</p>
<p><code><strong>Fatal error:</strong> Call to undefined function create() in /Document/Root/example.php on line 23</code></p>
<h3>Using var_dump() to Aid Your Debugging</h3>
<p>var_dump() is a native PHP function which displays structured, humanly readable, information about one (or more) expressions. This is particularly useful when dealing with arrays and objects as var_dump() displays their structure recursively giving you the best possible picture of what&#8217;s going on. Here&#8217;s an example of how to use var_dump() in context:</p>
<p>Below I have created an array of scores achieved by users but one value in my array is subtly distinct from the others, var_dump() can help us discover that distinction.</p>
<pre><code>&lt;?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);<br/><br/>
$aUserScores = array('Ben' => 7,'Linda' => 4,'Tony' => 5,'Alice' => '9');
echo '&lt;pre&gt;';
var_dump($aUserScores);
echo '&lt;/pre&gt;';</code></pre>
<p><em>Tip: Wrap var_dump() in &lt;pre&gt; tags to aid readability.</em></p>
<p>The output from var_dump() will look like this:</p>
<pre><code>array(4) {
  ["Ben"]=>
  int(7)
  ["Linda"]=>
  int(4)
  ["Tony"]=>
  int(5)
  ["Alice"]=>
  string(1) "9"
}</code></pre>
<p>As you can see var_dump tells us that $aUserScores is an array with four key/value pairs. Ben, Linda, and Tony all have their values (or scores) stored as integers. However, Alice is showing up as a string of one character in length.</p>
<p>If we return to my code, we can see that I have mistakenly wrapped Alice&#8217;s score of 9 in quotation marks causing PHP to interpret it as a string. Now, this mistake won&#8217;t have a massively adverse effect, however, it does demonstrate the power of var_dump() in helping us get better visibility of our arrays and objects.</p>
<p>While this is a very basic example of how var_dump() functions it can similarly be used to inspect large multi-dimensional arrays or objects. It is particularly useful in discovering if you have the correct data returned from a database query or when exploring a JSON response from say, Twitter:</p>
<p><code>&lt;?php<br />
ini_set('display_errors', 'On');<br />
error_reporting(E_ALL);<br/><br/><br />
$sJsonUrl = 'http://search.twitter.com/trends.json';<br/><br/><br />
$sJson = file_get_contents($sJsonUrl,0,NULL,NULL);<br />
$oTrends = json_decode($sJson);<br/><br/><br />
echo '&lt;pre&gt;';<br />
var_dump($oTrends);<br />
echo '&lt;/pre&gt;';</code></p>
<h3>Useful Tools to Consider when Debugging</h3>
<p>Finally, I want to point out a couple of useful tools that I&#8217;ve used to help me in the debugging process. I won&#8217;t go into detail about installing and configuring these extensions and add-ons, but I wanted to mention them because they can really make our lives easier.</p>
<p><strong>Xdebug</strong></p>
<p><a href="http://www.xdebug.org/" title="Xdebug">Xdebug</a> is a PHP extension that aims to lend a helping hand in the process of debugging your applications. Xdebug offers features like:</p>
<ul>
<li>Automatic stack trace upon error</li>
<li>Function call logging</li>
<li>Display features such as enhanced var_dump() output and code coverage information.</li>
</ul>
<p>Xdebug is highly configurable, and adaptable to a variety of situations. For example, stack traces (which are extremely useful for monitoring what your application is doing and when) can be configured to four different levels of detail. This means that you can adjust the sensitivity of Xdebug&#8217;s output helping you to get granular information about your app&#8217;s activity.</p>
<p>Stack traces show you where errors occur, allow you to trace function calls and detail the originating line numbers of these events. All of which is fantastic information for debugging your code.</p>
<p><em>Tip: As default Xdebug limits var_dump() output to three levels of recursion. You may want to change this in your xdebug.ini file by setting the xdebug.var_display_max_depth to equal a number that makes sense for your needs.</em></p>
<p>Check out <a href="http://www.xdebug.org/docs/install" title="Xdebug installation guide">Xdebug&#8217;s installation guide</a> to get started.</p>
<p><strong>FirePHP</strong></p>
<p>For all you <a href="https://addons.mozilla.org/en-US/firefox/addon/1843" title="FireBug">FireBug</a> fans out there, <a href="http://www.firephp.org/" title="FirePHP">FirePHP</a> is a really useful little PHP library and Firefox add-on that can really help with AJAX development.</p>
<p>Essentially FirePHP enables you to log debug information to the Firebug console using a simple method call like so:</p>
<p><code>&lt;?php<br />
	$sSql = 'SELECT * FROM tbl';<br />
	FB::log('SQL query: ' . $sSql);</code> </p>
<p>In an instance where I&#8217;m making an AJAX search request, for example, it might be useful to pass back the SQL string my code is constructing in order that I can ensure my code is behaving correctly. All data logged to the Firebug console is sent via response headers and therefore doesn&#8217;t effect the page being rendered by the browser.</p>
<p><em>Warning: As with all debug information, this kind of data shouldn&#8217;t be for public consumption. The downside of having to add the FirePHP method calls into your PHP is that before you go live you will either have to strip all these calls out or set up an environment based conditional statement which establishes whether or not to include the debug code.</em></p>
<p>You can install the Firefox add-on at <a href="http://www.firephp.org/" title="FirePHP">FirePHP&#8217;s website</a> and also <a href="http://www.firephp.org/HQ/" title="Fire PHP libs">grab the PHP libs</a> there too. Oh, and don&#8217;t forget if you haven&#8217;t already installed FireBug, <a href="https://addons.mozilla.org/en-US/firefox/addon/1843" title="FireBug">you&#8217;ll need that too</a>.</p>
<h3>In Conclusion &#8230;</h3>
<p>Hopefully during the course of this article you have learned how to do your ground work by preparing PHP for the debugging process; recognise and deal with the four key PHP error types and use var_dump() to your advantage. Likewise, I hope that you will find Xdebug and FirePHP useful and that they will make your life easier during your development cycle. </p>
<p>As I&#8217;ve already mentioned, and I really can&#8217;t say this enough, always remember to remove or suppress your debug output when you put your sites into production after all there&#8217;s nothing worse than all your users being able to read about your errors in excruciating detail.</p>
<p>Got a great debugging tip to share? Do you use a great little PHP extension that makes your bug trapping life easier? Please tell us about them in comments below!</p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3037&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/dev/how-to-debug-in-php/feed/</wfw:commentRss>
		<slash:comments>58</slash:comments>
		</item>
		<item>
		<title>How to Create Bulletproof Sessions</title>
		<link>http://carsonified.com/blog/dev/how-to-create-bulletproof-sessions/</link>
		<comments>http://carsonified.com/blog/dev/how-to-create-bulletproof-sessions/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 07:00:56 +0000</pubDate>
		<dc:creator>Robert Hafner</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=2955</guid>
		<description><![CDATA[By <strong>Robert Hafner</strong><br />
In the first part of this series we went over how a cookie works and what can be done to secure them. In this section we&#8217;re going to go over ways to add additional security to the session beyond the cookie itself.
By the end of this article we will written our own wrapper class for [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-create-bulletproof-sessions%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-create-bulletproof-sessions%2F" height="61" width="51" /></a></div><p><a href="http://events.carsonified.com/fowa/2009/london/schedule?utm_source=TV&amp;utm_medium=banner&amp;utm_campaign=Kevin%2Band%20Gary%20Show"><img src="http://ryancarson.com/uploads/kevin_gary.png" alt="Kevin and Gary show at FOWA London" /></a></p>
<p>In the first part of this series we went over <a href="http://carsonified.com/blog/dev/how-to-create-totally-secure-cookies">how a cookie works and what can be done to secure them</a>. In this section we&#8217;re going to go over ways to add additional security to the session beyond the cookie itself.</p>
<p>By the end of this article we will written our own wrapper class for &#8220;session_start&#8221; that protects  our session from a number of attacks while taking into account some of the unique challenges presented by modern ajax-heavy websites.</p>
<p><span id="more-2955"></span></p>
<h3>Session Specific Attacks</h3>
<p>Through the use of sessions your identity is maintained as you use a website, and just as in real life identity theft is a concern. By taking over your session an attacker would essentially become you on a website, with access to all of the actions, information and privileges that entails.</p>
<p>The main thing that an attacker needs to steal a session is the session ID. There are three ways an attacker normally goings about doing this, all of which can be protected against but are, by default, completely open.</p>
<ul>
<li>Guess the ID: most session handlers generate ids that make this impractical.</li>
<li>Steal the ID: by using malware, sniffing the network, or exploiting javascript exploits attackers can get the value from the cookie itself.</li>
<li>Set the ID: rather than steal or guess the ID an attacker may try and set it to a value they choose.</li>
</ul>
<h3>Starting the Session</h3>
<p>The default session setup is not at all secure by itself, so we&#8217;re going to create a wrapper to add the security we need. To make this code more portable we&#8217;re going to build it as a static function of a php class called SessionManager.</p>
<p>To begin our sessionStart function is going to set the name cookie options for the session. Like all cookies we&#8217;re going to need to make some decisions about what is going to need access to the session ID. Since these options depend on the application itself lets add arguments we can change based on our specific needs. </p>
<p>For security we can hardcode the &#8220;HttpOnly&#8221; argument, as session ids are often the juiciest target for cross site scripting attacks. </p>
<pre><code>class SessionManager
{
   static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
   {
      // Set the cookie name before we start.
      session_name($name . '_Session');

      // Set the domain to default to the current domain.
      $domain = isset($domain) ? $domain : isset($_SERVER['SERVER_NAME']);

      // Set the default secure value to whether the site is being accessed with SSL
      $https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);

      // Set the cookie settings and start the session
      session_set_cookie_params($limit, $path, $domain, $secure, true);
      session_start();
   }
}</code></pre>
<p>Using the new class is as easy as including it and running one line but additional options can make it more restrictive.</p>
<p><code>SessionManage::sessionStart('InstallationName');<br />
SessionManage::sessionStart('Blog_myBlog', 0, '/myBlog/', 'www.site.com');<br />
SessionManage::sessionStart('Accounts_Bank', 0, '/', 'accounts.bank.com', true);</code></p>
<h3>Lock the Session to a Host</h3>
<p>Now that our wrapper class is in place and functional we can start building in additional security by restricting the session to the same IP address and User Agent (or browser) as when the session was first opened. This way if the session ID is stolen or guessed the attacker still has to get ahold of the user agent (admittedly not too difficult if they got the session ID) and somehow find a way to get the same IP address.</p>
<p>These attacks only help if the user is not on the same network. The user agent check only adds minor security, since many attacks that compromise the cookie are going to do the same to the user agent. If an attacker is on the same network as the target there is a good chance they already have the same external IP address, as it is pretty common for a network to use private internal addresses while presenting only a single IP address to the internet. This is why it is important to evaluate the need for SSL.</p>
<p>We&#8217;re going to add these new checks to our class in the function preventHijacking. This function will return false on new sessions or when a session is loaded by a host with a different IP address or browser. preventHijacking will true if the session is valid and false otherwise. This means it will return false not just on malicious attempts but completely new sessions as well.</p>
<pre><code>static protected function preventHijacking()
{
	if(!isset($_SESSION['IPaddress']) || !isset($_SESSION['userAgent']))
		return false;

	if ($_SESSION['IPaddress'] != $_SERVER['REMOTE_ADDR'])
		return false;

	if( $_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT'])
		return false;

	return true;
}</code></pre>
<p>Now that we have a way to identify hijacking attempts we need to set up a way to respond to them. For us this means two things- clearing out the old session data and inserting the IP address and user agent into the new session.</p>
<pre><code>static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
	...
	session_start();

	if(!self::preventHijacking())
	{
		$_SESSION = array();
		$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
		$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
	}
}</code></pre>
<h3>Session Fixation</h3>
<p>So far we have effectively eliminated the possibility of brute force guessing. We&#8217;ve also made it so any attempts at capturing the session ID would require the attacker to be on the same network as the user in order to take advantage of that ID, while also discussing enforcing SSL to make capturing the session more difficult through traditional means. However, what if the attacker could set the session ID themselves?</p>
<p>By getting the user to follow a link with a session ID in it the attacker can trick the user into starting a session with the ID of the attacker&#8217;s choosing. Rather than guess or steal an ID the attacker will have it right from the start. Many web environments, including PHP, allow session ids to be set through the URL, primarily to get around systems which do not support cookies. Just like with regular cookies the value sent by the client is the value used for the ID, so in this case the value in the URL becomes the session ID.</p>
<p>The solution to this is to change the session ID. How often you do this is tends to be a matter of great debate, but at the bare minimum the ID should be changed when new sessions are created and when the user changes privileges (logs in or out).</p>
<h3>A First Attempt At Regenerating the ID</h3>
<p>Regenerating the ID is fairly simply in php. Deceptively simple one might say. The function &#8220;session_regenerate_id&#8221; lets us tell the system to use a new ID.  It can also optionally delete the old session.</p>
<pre><code>// Leaves old session intact
session_regenerate_id();

// Deletes old session
session_regenerate_id(true);</code></pre>
<p>If you don&#8217;t delete the old session then it is still vulnerable to hijacking and whatever access it had can be granted to an attacker. If you&#8217;re changing the session ID often without deleting the old ones you could be creating more holes by leaving a trail of old, but valid, sessions.</p>
<h3>Regenerating the ID in the World of Ajax</h3>
<p>If an application creates a lot of quick connections to the server some interesting things can happen. PHP, and many other languages, restricts access to the session data to one running script at a time, so if multiple requests come in that try to access the session data the second request (and any other) gets queued up. When the first request changes the ID and deletes the old session the second request still has the old session ID which no longer exists. This results in a third, new session being opened and generally means your user gets logged out.</p>
<p>This bug is ridiculously hard to diagnose as the timing of not just the requests but the ID regeneration has to be just right. In sites that don&#8217;t make requests to the server using javascript this type of bug may never be encountered at all, as the time between page loads is more than long enough for the browser to have updated its session info. For sites that make use of ajax techniques, however, this issue will have a chance of occurring whenever the session ID is changed.</p>
<p>In our final update to the SessionManager class we&#8217;re going to write a fix for this problem. Rather than delete the session immediately when we change the ID, we&#8217;re going to mark the old session as obsolete and mark it to expire in ten seconds. This way any queued up requests will still have access to the expired session but we don&#8217;t have to leave it open forever.</p>
<p>To accomplish this we&#8217;re going to add the regenerateSession function. This function adds the obsolete flag and expiration to the session, regenerates the ID to create the new session and saves them both. It  then reopens the new session and removes the obsolete flag. Unlike our other internal functions we are leaving this one open for use outside the class so that it can be tied into login scripts.</p>
<pre><code>static function regenerateSession()
{
	// If this session is obsolete it means there already is a new id
	if(isset($_SESSION['OBSOLETE']) || $_SESSION['OBSOLETE'] == true)
		return;

	// Set current session to expire in 10 seconds
	$_SESSION['OBSOLETE'] = true;
	$_SESSION['EXPIRES'] = time() + 10;

	// Create new session without destroying the old one
	session_regenerate_id(false);

	// Grab current session ID and close both sessions to allow other scripts to use them
	$newSession = session_id();
	session_write_close();

	// Set session ID to the new one, and start it back up again
	session_id($newSession);
	session_start();

	// Now we unset the obsolete and expiration values for the session we want to keep
	unset($_SESSION['OBSOLETE']);
	unset($_SESSION['EXPIRES']);
}</code></pre>
<p>We need to add another function to check for the obsolete flag and to see if the session has expired.</p>
<pre><code>static protected function validateSession()
{
	if( isset($_SESSION['OBSOLETE']) &amp;&amp; !isset($_SESSION['EXPIRES']) )
		return false;

	if(isset($_SESSION['EXPIRES']) &amp;&amp; $_SESSION['EXPIRES'] &lt; time())
		return false;

	return true;
}</code></pre>
<p>Finally, in the last change to our SessionManager, we need to update our SessionStart function. It needs to call the regenerateSession function on new requests and periodically after that, as well as destroy the session if it is invalid. Here is the complete SessionStart function.</p>
<pre><code>static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
	// Set the cookie name
	session_name($name . '_Session');

	// Set SSL level
	$https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);

	// Set session cookie options
	session_set_cookie_params($limit, $path, $domain, $https, true);
	session_start();

	// Make sure the session hasn't expired, and destroy it if it has
	if(self::validateSession())
	{
		// Check to see if the session is new or a hijacking attempt
		if(!self::preventHijacking())
		{
			// Reset session data and regenerate id
			$_SESSION = array();
			$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
			$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
			self::regenerateSession();

		// Give a 5% chance of the session id changing on any request
		}elseif(rand(1, 100) &lt;= 5){
			self::regenerateSession();
		}
	}else{
		$_SESSION = array();
		session_destroy();
		session_start();
	}
}</code></pre>
<h3>Summery</h3>
<p>At times it amazes me how complex something as simple as an ID- what is essentially just a string of random characters- can turn out to be. While you can certainly use this class for all of your own projects here is what you need to remember when building your own session manager.</p>
<p>Session IDs are attacked by guessing, capturing or setting the id. You can protect against this in your own applications by &#8230;</p>
<ul>
<li>Securing the cookie to make stealing the ID harder</li>
<li>Limiting the session to a specific host to make attacks more difficult</li>
<li>Changing the ID when escalating privileges and throughout the session life.</li>
</ul>
<p>Here is the complete <a href="http://ryancarson.com/uploads/securingcookies/Session.class.php.zip">Session.class.php file</a> for your reference.</p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=2955&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/dev/how-to-create-bulletproof-sessions/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>How to Create Totally Secure Cookies</title>
		<link>http://carsonified.com/blog/dev/how-to-create-totally-secure-cookies/</link>
		<comments>http://carsonified.com/blog/dev/how-to-create-totally-secure-cookies/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 07:00:38 +0000</pubDate>
		<dc:creator>Robert Hafner</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=2945</guid>
		<description><![CDATA[By <strong>Robert Hafner</strong><br />
Securing cookies and sessions is vital to keeping an application secure. Many tutorials have been written on the subject, but as the internet (and browsers loading it) evolve so do the methods you can use to keep your application secure.
In this article we&#8217;re going to break down the various components of a cookie and what [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-create-totally-secure-cookies%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-create-totally-secure-cookies%2F" height="61" width="51" /></a></div><p><a href="http://events.carsonified.com/fowa/2009/london/schedule?utm_source=TV&amp;utm_medium=banner&amp;utm_campaign=Kevin%2Band%20Gary%20Show"><img src="http://ryancarson.com/uploads/kevin_gary.png" alt="Kevin and Gary show at FOWA London" /></a></p>
<p>Securing cookies and sessions is vital to keeping an application secure. Many tutorials have been written on the subject, but as the internet (and browsers loading it) evolve so do the methods you can use to keep your application secure.</p>
<p>In this article we&#8217;re going to break down the various components of a cookie and what they mean for security. This will include limiting the cookie to certain domains and paths on those domains, choosing what information to store, and protecting the cookie from cross site scripting exploits. In a second article we will go into more depth in how to protect everyone&#8217;s favorite cookie, the session ID.</p>
<p><span id="more-2945"></span></p>
<h3>How Cookies Work</h3>
<p>Cookies are simply key/value pairs that let us get around HTTP being a stateless protocol. When a developer has data they wish to last for more than one connection they can use cookies to store that data on the client side. While this tends to get handled by the programming language being used it is accomplished using HTTP headers.</p>
<p>When the server wants to set a cookie it passes back a header named &#8220;Set-Cookie&#8221; with the key-value pair and some options.</p>
<p><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-setcookie.png"><img src="http://ryancarson.com/uploads/securingcookies/smaller-liveheaders-setcookie.png" alt="The HTTP server responds with Set-Cookie: Test_Session=f8daa3ad35a272514a18039e8a93b204; path=/; HttpOnly" /></a><br /><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-setcookie.png">View larger</a></p>
<p>On subsequent requests the client will send along its own header to let the server know the name and value of its stored cookies. The server will not continue to send back the cookies, it will only send them if there is a change.</p>
<p><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-clientcookie.png"><img src="http://ryancarson.com/uploads/securingcookies/smaller-liveheaders-clientcookie.png" alt="The browser sends the server Set-Cookie: Cookie: Test_Session=f8daa3ad35a272514a18039e8a93b204" /></a><br /><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-clientcookie.png">View larger</a></p>
<p>You can see all the headers for yourself using the LiveHeaders plugin for Firefox.</p>
<h3>The Problem</h3>
<p>This data is completely in control of the client- it is trivial to change the values of a cookie. That means that, just like post and get data, all cookie data must be validated in some way. At the same time you&#8217;ll want to avoid storing sensitive information, such as passwords, as cookies are stored in cleartext and anyone with access to the computer later can easily pick those up (I know of at least one security forum that was hacked in this way).  It is also important to note that HTTP does not encrypt the headers in any way. If the connection isn&#8217;t over SSL then it will not be protected from snooping eyes.</p>
<p>Session cookies are no different than any other cookie- their value is just a simple ID. Those IDs are susceptible to all of the same limitations as other cookies. The real power behind sessions happens server side, where the ID is used to pull out data stored on the server. This has many benefits over storing data directly into the cookie itself- data can&#8217;t be manipulated by the user, large amount of data can be stored without having to send it back and forth with each request, and you can store data you otherwise wouldn&#8217;t want the client to have access to.</p>
<h3>Getting Started</h3>
<p>The first step towards securing your cookie is to restrict that cookie to only your application. This is especially important in environments that support multiple sites or applications (the type of shared hosting you often see on corporate or university domains). By restricting the cookie to only  the applications that need it you reduce the chances of it being sniffed while also keeping the cookie namespaces clear for other applications that use them.</p>
<p>There are three options that can be sent along when creating a cookie that, when used properly, will keep the cookie limited to only your application. Before setting these options you will need to ask yourself a few questions-</p>
<ul>
<li>What parts of the website need access to the cookie?</li>
<li>Will the cookie need to work across sub domains?</li>
<li>Will the cookie need to persist if the user leaves an SSL portion of the site?</li>
</ul>
<p>There is also a forth option used by newer browsers to restrict access to cookies by javascript.</p>
<p>As you will see, how exactly to restrict the cookie really does depend on the exact purpose for that cookie. A banking or ecommerce site may restrict their cookies to only SSL, while a blog or news aggregator may want to leave things more open.</p>
<h3>Cookie Options</h3>
</p>
<p><b>Send The Cookie To Only Your Application</b></p>
<p>The Path argument specifies what paths on the site to send the cookie. The default value of &#8220;/&#8221; means every request will get the cookie, while &#8220;/forums/&#8221; would limit the cookie to just that path. This path is going to be based on the actual URL the browser uses, before any mod_rewrite or other URL mapping.</p>
<p><b>Don&#8217;t Share With Sub Domains</b></p>
<p>The Domain option allows you to specify whether or not to send the cookie to subdomains. Setting &#8220;www.example.com&#8221; will mean only the exact domain &#8220;www.example.com&#8221; will be matched, while &#8220;.example.com&#8221; will also match again any subdomaim (forums.example.com, blog.example.com).</p>
<p><b>Require a Secure Connection</b></p>
<p>Using the Secure option you can tell the browser (or other http clients) to only send the cookie over SSL connections. This means the cookie will not be available to any part of the site that is not secure will not have access to the cookie, but it also makes it much less likely that you&#8217;ll accidentally send the cookie across as cleartext.</p>
<p><b>Protect Against XSS Exploits</b></p>
<p>This HttpOnly flag is used to tell the browser that it should not allow javascript to access the contents of the cookie. This is primarily a defense against cross site scripting, as it will prevent hackers from being able to retrieve and use the session  through such an attack.</p>
<p>The HttpOnly option is not by any means full proof. As a client-side defense mechanism it relies on browser support to work, but is only supported by a few browsers (Firefox 3+ and IE 7+, with partial support from Opera 9.5, IE6 and Chrome).</p>
<h3>Configuring the Cookie</h3>
<p>In PHP, setting the arguments for cookies is done through some optional arguments on the &#8220;setcookie&#8221; function:</p>
<pre><code>setcookie( name, value, expire, path, domain, secure, httponly);

// Open
setcookie( 'UserName', 'Bob', 0, '/', '.example', false, false);

// Locked Down
setcookie( 'UserName', 'Bob', 0, '/forums', 'www.example.com', isset($_SERVER["HTTPS"]), true);</code></pre>
<p>To change the cookie values for the session cookie requires the &#8220;session_set_cookie_params&#8221; function, which needs to be called before the session is started.</p>
<pre><code>session_set_cookie_params($expire, $path, $domain, $secure, true);

// Open
session_set_cookie_params(0, '/', '.example', false, false);

// Locked Down
session_set_cookie_params('o, /forums', 'www.example.com', isset($_SERVER["HTTPS"]), true)</code></pre>
<h3>Summary</h3>
<p>Cookies remain the basic method of identify tracking on most websites and keeping them secure is a vital part to keeping applications as a whole locked down and secure. In this article we went over four methods for protecting cookies on a general level.</p>
<p>When using cookies its important to remember to:</p>
<ul>
<li>Limit the amount of sensitive information stored in the cookie.</li>
<li>Limit the subdomains and paths to prevent interception by another application.</li>
<li>Enforce SSL so the cookie isn&#8217;t sent in cleartext.</li>
<li>Make the cookie HttpOnly so its not accessible to javascript.</li>
</ul>
<p>Please check out the second half of this series, where we&#8217;re going to take the next step with an in depth guide to securing sessions.</p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=2945&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/dev/how-to-create-totally-secure-cookies/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>5 Advanced Photoshop Techniques for Web Designers</title>
		<link>http://carsonified.com/blog/design/5-advanced-photoshop-techniques-for-web-designers/</link>
		<comments>http://carsonified.com/blog/design/5-advanced-photoshop-techniques-for-web-designers/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 10:19:23 +0000</pubDate>
		<dc:creator>Marko Prljić</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Photoshop]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=3005</guid>
		<description><![CDATA[By <strong>Marko Prljić</strong><br />If we look at web design today, it&#8217;s anything but simple. Sometimes you need that extra Photoshop knowledge in order to achieve the look we need.
In this step-by-step tutorial, I&#8217;m going to show you how to create five killer effects for your site.

When I was choosing examples for this article I visited some design galleries [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdesign%2F5-advanced-photoshop-techniques-for-web-designers%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdesign%2F5-advanced-photoshop-techniques-for-web-designers%2F" height="61" width="51" /></a></div><p>If we look at web design today, it&#8217;s anything but simple. Sometimes you need that extra Photoshop knowledge in order to achieve the look we need.</p>
<p>In this step-by-step tutorial, I&#8217;m going to show you how to create five killer effects for your site.</p>
<p><span id="more-3005"></span></p>
<p>When I was choosing examples for this article I visited some design galleries and roundup posts and took screenshots of design details that are used (sometimes overused) in web design. I don&#8217;t encourage you to follow trends but rather develop your own style. Nevertheless, it is always useful to polish your Photoshop skills a bit more. Let&#8217;s get rockin&#8217;!</p>
<p><em>Editor&#8217;s Note: Andy Clarke will be teaching an interesting session called &#8220;How to Design in the Browser&#8221; and Elliot Jay Stocks will be showing you how to design the &#8220;The Perfect Portfolio&#8221; at <a href="http://events.carsonified.com/fowd/2009/tour?utm_source=TV&#038;utm_medium=Text%2Blink&#038;utm_campaign=5%2BAdvanced%20Photoshop%20Techniques%20for%20Web%20Design">The Future of Web Design Tour</a>.</em></p>
<h3>#1 Awesome Buttons</h3>
<p>Now what is a site without a great &#8220;Call to action&#8221; button? The design style and colors will depend on your overall site style and importance of each button. Here is one example of a simple but effective button that we&#8217;ll be trying to recreate (taken from <a href="http://www.transmissionapps.com">transmissionapps.com</a>).</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/buttons.jpg" /></p>
<p><strong>Step 1</strong></p>
<p>Open New Document, set canvas to 470px wide and 350px high. Create a new layer and draw in this shape with Rounded Rectangle Tool with radius set to 80px.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_1.png" /></p>
<p><strong>Step 2</strong></p>
<p>Right after that we will add some layer filters to make this button immediately awesome. Drop Shadow &#8211; Color: Black, Opacity:65%, Distance: 2px, Size:2px, the rest leave by default.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_2.png" /></p>
<p><strong>Step 3</strong></p>
<p>Gradient Overlay. Just copy these hex codes for gradient colors and place color buckets in approximately same position as you can see in the image.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_3.png" /></p>
<p><strong>Step 4</strong></p>
<p>Inner Shadow will make this button stand out even more. Notice that this is just a subtle effect. Inner Shadow &#8211; Color: Black, Opacity: 15%, Distance: 0px, Size: 5px; </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_4.png" /></p>
<p><strong>Step 5</strong></p>
<p>Finally add some Stroke. You will notice that this is a Gradient Stroke with same colors as our buttons Gradient Overlay. The only difference here is that gradient direction is set -90, which is the opposite of buttons Gradient Overlay. With this little trick we made a nice light effect to our button and made it stand out a bit more.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_5.png" /></p>
<p><strong>Step 6</strong></p>
<p>Done with effects, time for some shine! Create a new layer above others.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_6.png" /></p>
<p><strong>Step 7</strong></p>
<p>Cmnd (Ctrl) + Click on Button shape layer. We have made a selection out of it.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_7.png" /></p>
<p><strong>Step 8</strong></p>
<p>Choose Marquee Tool. Hold down the Alt key and Subtract the half from selection.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_8.png" /></p>
<p><strong>Step 9</strong></p>
<p>Choose Black to White Gradient Tool, set the layer mode to Screen and pull upwards from bottom of selection to about 30px outside the selection. There you have it! A nice shiny button. </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_9.png" /></p>
<p><strong>Step 10</strong></p>
<p>Add some text like I did here. Draw in a circle and position it like you see it in the picture. Add a Gradient Overlay with same values like shown in the screenshot. Finally give it a 2px white Inside stroke.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_10a.png" /><br />
<img src="http://ryancarson.com/uploads/photoshop-tut/button_10.png" /></p>
<p><strong>Step 11</strong></p>
<p>Choose Shape Tool. From presets choose an Arrow. Rotate it.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_11.png" /></p>
<p><strong>Step 12</strong></p>
<p>Like the image says, position the arrow in bottom direction.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_12.png" /></p>
<p><strong>Step 13</strong></p>
<p>Now choose Direct Selection Tool and select the shape. Next, select two points from upper part of the arrow and move them with Arrow Keys few pixels to the right. Do the same with the right top side of the arrow, just shift it to the left. This way our top part will become a bit thiner. With the same tool adjust the bottom part (triangle).</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_13.png" /></p>
<p><strong>Step 14</strong></p>
<p>This is how it should look like. You can also see the layer structure.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/button_14.png" /></p>
<h3>#2 Navigation Menus</h3>
<p>The most important part of a website: the navigation. I&#8217;ve chosen the example that uses some transparency and fade out effect (taken from <a href="http://legacylocker.com/">legacylocker.com</a>).</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav.jpg" /></p>
<p><strong>Step 1</strong></p>
<p>Open a New Document, same dimensions from previous example. Create a New Layer and fill it with Gradient Overlay using the color hex values you can see in the image.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_1.png" /></p>
<p><strong>Step 2</strong></p>
<p>For the purpose of this example I added few clouds :)</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_2.png" /></p>
<p><strong>Step 3</strong></p>
<p>Draw in a Rectangle, paint it with #6bb9ec and set Opacity to 65%.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_3.png" /></p>
<p><strong>Step 4</strong></p>
<p>Add a Quick Mask to this layer. Choose 200px radius Soft Brush, set the color to Black and mask the ends of this rectangle, like you see it in the image.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_4.png" /></p>
<p><strong>Step 5</strong></p>
<p>Draw in another Rectangle, but much higher. Put it under the small rectangle. Use the same color and Opacity. Again add a Quick Mask to this layer. </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_5.png" /></p>
<p><strong>Step 6</strong></p>
<p>Choose 600px Soft Brush and carefully mask bottom of the rectangle os that top line stays visible across the document.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_6.png" /></p>
<p><strong>Step 7</strong></p>
<p>Now we can play a bit with the small Rectangle by adding some light and shadows. Cmnd (Ctrl) + Click small Rectangle to make a selection out of it. Go to Select>Modify>Contract and enter 1px. Create a New layer and set Mode to Overlay. Choose 200px Soft Brush, color white and click few times the top part of the rectangle just like you see in the image. </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_7.png" /></p>
<p><strong>Step 8</strong></p>
<p>Do the same with bottom part just change the Brush color to Black.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_8.png" /></p>
<p><strong>Step 9</strong></p>
<p>Here you can see how this looks like. It&#8217;s really a subtle effect of light and shadow which you can use wherever you want.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_9.png" /></p>
<p><strong>Step 10</strong></p>
<p>With Line Tool draw in a line just the same width as small rectangle. For color choose #8dd1fe. </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_10.png" /></p>
<p><strong>Step 11</strong></p>
<p> Mask the ends of the line just like we did in Step 4. Copy this line and shift it to the bottom of the small rectangle.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_11.png" /></p>
<p><strong>Step 12</strong></p>
<p>Finally I added some Navigation items and that&#8217;s it!</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/nav_12.png" /></p>
<h3>#3 Typography Inset</h3>
<p>Even though we&#8217;re used to seeing this technique now, it&#8217;s still a good skill to add to your toolbox. Please use it only if you have to :) The example was taken from <a href="http://forabeautifulweb.com">forabeautifulweb.com</a>.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_inset.jpg" /></p>
<p><strong>Step 1</strong></p>
<p>Same New Document filled with #aa8e5c.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_1.png" /></p>
<p><strong>Step 2</strong></p>
<p>I added some floral brushes just to recreate the same background from the example :)</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_2.png" /></p>
<p><strong>Step 3</strong></p>
<p>Choose Type Tool, set font to Times New Roman. Choose color #591e0d and type something.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_3.png" /></p>
<p><strong>Step 4</strong></p>
<p>Add Inner Shadow filter and use settings like shown in the image.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_4.png" /></p>
<p><strong>Step 5</strong></p>
<p>Add 2px Outside Stroke with color set to #bc9f6c.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_5.png" /></p>
<p><strong>Step 6</strong></p>
<p>Done! What, that&#8217;s it? Yes, that&#8217;s it! Simple and effective.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/type_6.png" /></p>
<h3>#4 Faded Shadow</h3>
<p>With a little bit of Blur and Quick Mask we can create shadows that fade out in any direction we want to. With this effect you can make boxes look like they pop out of the background. This example is from <a href="http://www.mint.com">mint.com</a>.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/fade_shadow.jpg" /></p>
<p><strong>Step 1</strong></p>
<p>First thing first, the background. As usual by now, within New Document same dimensions like previous ones.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/faded_shadow_1.png" /></p>
<p><strong>Step 2</strong></p>
<p>Draw in a white Rectangle.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/faded_shadow_2.png" /></p>
<p><strong>Step 3</strong></p>
<p>Create a New Layer and place it under the white rectangle layer. Cmnd (Ctrl) + Click white rectangle shape. Fill the empty layer with Black.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/faded_shadow_3.png" /></p>
<p><strong>Step 4</strong></p>
<p>Go to Filter>Blur>Gaussian Blur and enter Radius: 12px.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/faded_shadow_4.png" /></p>
<p><strong>Step 5</strong></p>
<p>Add a Quick Mask to this layer. Select a 300px Soft Brush Tool and carefully mask all </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/faded_shadow_5.png" /></p>
<p><strong>Step 6</strong></p>
<p>Now this was pretty easy, don&#8217;t you think? Now you can play around with this technique and who knows what awesome results you&#8217;ll get.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/faded_shadow_6.png" /></p>
<h3>#5 Depth and 3D Space</h3>
<p>More and more interesting 3D elements are being used in web design lately. Here you can see how with just few extra layers, you can create an illusion of 3D space. This example is from <a href="http://www.mosaiko.com.br">mosaiko.com.br</a>.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth.jpg" /></p>
<p><strong>Step 1</strong></p>
<p>New Document filled with Black.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_1.png" /></p>
<p><strong>Step 2</strong></p>
<p>With Rectangle Toll draw in rectangle and fill it with #21262a.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_2.png" /></p>
<p><strong>Step 3</strong></p>
<p>With same tool selected draw in another, this time smaller rectangle and fill it with #191b1d. These two rectangles will create our space on canvas. It will look like a wall is passing through it.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_3.png" /></p>
<p><strong>Step 4</strong></p>
<p>Cmnd (Ctrl) + Click bigger rectangle shape to get a selection. Create a New layer. Choose 300px Soft Brush, color Black and click few times in top center of the selection.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_4.png" /></p>
<p><strong>Step 5</strong></p>
<p>Do the same with smaller rectangle but this time click on bottom center part of the rectangle.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_5.png" /></p>
<p><strong>Step 6</strong></p>
<p>Now, do the same for the background layer itself just use White as Brush color.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_6.png" /></p>
<p><strong>Step 7</strong></p>
<p>Draw in a 85&#215;20 px rectangle, fill it with #555759.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_7.png" /></p>
<p><strong>Step 8</strong></p>
<p>Add following effects. Drop Shadow &#8211; Color: Black, Opacity: 25%, Angle: 90, Distance: 1px, Size:4px. Inner Shadow &#8211; Color: White, Opacity: 7%, Angle: -90, Distance: 1px, Size: 2px. Gradient Overlay, use values provided in the image.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_8a.png" /><br />
<img src="http://ryancarson.com/uploads/photoshop-tut/depth_8.png" /></p>
<p><strong>Step 9</strong></p>
<p>Choose Pen Tool and draw in a shape like you see in the image. Fill it with #555759.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_9.png" /></p>
<p><strong>Step 10</strong></p>
<p>With a little use of Quick Mask and some Brushing we will create the illusion of 3D space. First add a Quick Mask to the layer and with 100 px Soft Brush mask the sides of the stripe.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_10.png" /></p>
<p><strong>Step 11</strong></p>
<p>Next, select the whole stripe and choose 100px Soft Brush again. Create New Layer, set color to white and click few times at the beginning of the path but only with the top of the brush just like shown in the image. </p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_11.png" /></p>
<p><strong>Step 12</strong></p>
<p>I added some navigation links, copied few more stripes, modified the perspective a bit and there we have it.</p>
<p><img src="http://ryancarson.com/uploads/photoshop-tut/depth_12.png" /></p>
<p>I hope you enjoyed it and hopefully learned something new. Watch out for Part 2 where we will be covering more interesting Photoshop techniques.</p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=3005&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/design/5-advanced-photoshop-techniques-for-web-designers/feed/</wfw:commentRss>
		<slash:comments>128</slash:comments>
		</item>
		<item>
		<title>How to Get Started with the Twitter API</title>
		<link>http://carsonified.com/blog/dev/how-to-get-started-with-the-twitter-api/</link>
		<comments>http://carsonified.com/blog/dev/how-to-get-started-with-the-twitter-api/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 06:52:58 +0000</pubDate>
		<dc:creator>Kari Pätilä</dc:creator>
				<category><![CDATA[APIs]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=2980</guid>
		<description><![CDATA[By <strong>Kari Pätilä</strong><br />
Thanks to some very nice open source libraries for quite a few programming languages, interacting with the Twitter API has become exceedingly simple. In this article we&#8217;ll be looking at different ways to pull in data from Twitter.

The libraries page of Twitter&#8217;s API wiki is a good place to start. For these examples I&#8217;m going [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style=""><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-get-started-with-the-twitter-api%2F"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fdev%2Fhow-to-get-started-with-the-twitter-api%2F" height="61" width="51" /></a></div><p><a href="http://events.carsonified.com/fowa/2009/london/schedule?utm_source=TV&amp;utm_medium=banner&amp;utm_campaign=Kevin%2Band%20Gary%20Show"><img src="http://ryancarson.com/uploads/kevin_gary.png" alt="Kevin and Gary show at FOWA London" /></a></p>
<p>Thanks to some very nice open source libraries for quite a few programming languages, interacting with the Twitter API has become exceedingly simple. In this article we&#8217;ll be looking at different ways to pull in data from Twitter.</p>
<p><span id="more-2980"></span></p>
<p>The <a href="http://apiwiki.twitter.com/Libraries">libraries page</a> of Twitter&#8217;s API wiki is a good place to start. For these examples I&#8217;m going to use the <a href="http://code.google.com/p/php-twitter/">php-twitter</a> class, but I&#8217;ll include the requests and responses so this doesn&#8217;t turn out to be all PHP. After all, the API itself doesn&#8217;t care which language I&#8217;m using.
</p>
<p>The php-twitter <a href="http://php-twitter.googlecode.com/files/php-twitter-1.1.zip">zip archive</a> contains some nested folders and finally a file: class.twitter.php. You&#8217;ll eventually get to it, so keep opening those folders!
</p>
<h3>Getting your timeline from Twitter</h3>
<p>With this library you don&#8217;t have to worry about data exchange formats (the default is JSON), but if you&#8217;re still stuck with PHP 4, you might have to set the $type variable to &#8216;xml&#8217;. But, let&#8217;s face it: if you enjoy XML you&#8217;re kind of insane, aren&#8217;t you? If your host is still using PHP 4, chances are that they&#8217;ll update you to the latest version if you ask them nicely.
</p>
<p>The API method we&#8217;ll be using is <a href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-user_timeline">user_timeline</a>. You can check out the output by pointing your browser to <a href="http://twitter.com/statuses/user_timeline/karipatila.xml">http://twitter.com/statuses/user_timeline/karipatila.xml</a>. Notice the &#8220;.xml&#8221; &mdash; that&#8217;s the data exchange format. You can use &#8220;json&#8221;, &#8220;rss&#8221; or &#8220;atom&#8221; there as well. That URL is the GET request the API is responding to, which could be made using any programming language.
</p>
<p>So, using the library, this is all we need to fetch my timeline:</p>
<pre><code>&lt;?php
header('Content-type: text/html; charset=utf-8');
require_once 'class.twitter.php';
$t = new twitter;
$data = $t->userTimeline('karipatila');
?&gt;</code></pre>
<p>First we make sure the script can handle unicode characters and then we include class.twitter.php. Next we&#8217;ll set up a new instance of the php-twitter class, which can be used to pull in some data.</p>
<p>The script loads the timeline from Twitter and stores it into the $data variable. Along with some user information it contains the tweets themselves, which are what we&#8217;re really interested in. Let&#8217;s take a look at what kind of information we&#8217;re getting. This is one of my tweets in the $data array:
</p>
<pre><code><strong>[truncated] => </strong>
<strong>[text] => </strong>TomTom Nordic, 69,90&euro;: http://bit.ly/wX51t (App Store link) - wonder how expensive the car kit is?

<strong>[in_reply_to_status_id] => </strong>
<strong>[created_at] => </strong>Mon Aug 17 07:55:51 +0000 2009
<strong>[favorited] => </strong>
<strong>[in_reply_to_user_id] => </strong>
<strong>[id] => </strong>3358348095

<strong>[in_reply_to_screen_name] => </strong>
<strong>[source] => </strong>&lt;a href="http://www.atebits.com/" rel="nofollow"&gt;Tweetie&lt;/a&gt;</code></pre>
<p>We can use that information to make a script that lists my recent tweets. The API method <em>statuses user_timeline</em> returns the 20 most recent statuses posted from the authenticating user. I also wanted to link back to the accounts that are being replied to, so I&#8217;m looking for an @ symbol followed by one or more word characters and linking them to their respective Twitter profiles:
</p>
<pre><code>&lt;ul&gt;
	&lt;?php foreach($data as $d){ ?&gt;
	&lt;li&gt;&lt;?php echo preg_replace('/(^|\s)@(\w+)/','\1&lt;a href="http://twitter.com/\2"&gt;@\2&lt;/a&gt;', $d-&gt;text); ?&gt;&lt;/li&gt;

	&lt;?php } ?&gt;
&lt;/ul&gt;</code></pre>
<p>A short note on <a href="http://apiwiki.twitter.com/Rate-limiting">rate limitations</a>; caching the output from this script will become necessary sooner or later. The technical details are beyond the scope of this article, but you might want to consider saving the output into a database or a file and checking for updates every couple of minutes or so. A limit of 150 requests per hour applies to the REST API.</p>
<p>Get the source for fetching a user&#8217;s timeline <a href="http://ryancarson.com/uploads/user_timeline.php.txt">here</a>.</p>
<h3>Let&#8217;s look for treasure</h3>
<p>For example, let&#8217;s do a search for the hashtag &#8220;#carsonified&#8221;. They have recently announced <a href="http://hello.carsonified.com/">Hello App</a>, so there should be some chatter around that subject. We can add terms to the search like this:</p>
<p><code>$data = $s->search('#carsonified OR #HelloApp');</code></p>
<p>The search API method requires the query to be <a href="http://en.wikipedia.org/wiki/URL_encoding">URL encoded</a>, so we replace # with %23 in the request: <a href="http://search.twitter.com/search.json?q=%23carsonified&#038;rpp=5&#038;page=1">http://search.twitter.com/search.json?q=%23carsonified&#038;rpp=5&#038;page=1</a>. The search API accepts either &#8220;json&#8221; or &#8220;atom&#8221; as the exchange format.</p>
<p>If we break that request down, we find it contains the following information:</p>
<pre><code>q=[query string]
rpp=[results per page]
page=[page number]</code></pre>
<p>The search API has virtually no rate limits, so you don&#8217;t have to worry about your app getting throttled. Note that this time we&#8217;re also creating another instance with</p>
<p><code>$s = new summize;</code></p>
<p>which refers to the search class found in the php-twitter library.</p>
<pre><code>&lt;?php
header('Content-type: text/html; charset=utf-8');
require_once 'class.twitter.php';
$t = new twitter;

$s = new summize;
$data = $s->search('#carsonified');
$data = $data->results;
?&gt;</code></pre>
<p>In this example one tweet stored in $data might contain the following information:</p>
<pre><code><strong>[text] => </strong>Just trying out Matt by #carsonified. uniquely designed site with workable UI.
<strong>[to_user_id] => </strong>
<strong>[from_user] => </strong>_midnightshad
<strong>[id] => </strong>3284756132
<strong>[from_user_id] => </strong>2270963

<strong>[iso_language_code] => </strong>en
<strong>[source] => </strong>&lt;a href=&quot;http://themattinator.com&quot; rel=&quot;nofollow&quot;&gt;Matt&lt;/a&gt;
<strong>[profile_image_url] => </strong>http://a1.twimg.com/profile_images/60040548/panda_normal.jpg

<strong>[created_at] => </strong>Thu, 13 Aug 2009 11:50:01 +0000</code></pre>
<p>We can use this to make a simple listing based on the results:</p>
<pre><code>&lt;?php
header('Content-type: text/html; charset=utf-8');
require_once 'class.twitter.php';

$t = new twitter;
$s = new summize;
$data = $s->search('#carsonified');
$data = $data->results;
?&gt;
&lt;ul&gt;

&lt;?php foreach($data as $d){ ?&gt;
	&lt;li&gt;
		&lt;img src="&lt;?php echo $d-&gt;profile_image_url; ?&gt;" alt="" /&gt;
		&lt;?php echo preg_replace('/(^|\s)@(\w+)/','\1&lt;a href="http://twitter.com/\2"&gt;@\2&lt;/a&gt;', $d-&gt;text); ?&gt;

		&lt;em&gt;by&lt;/em&gt;
		&lt;a href="http://twitter.com/&lt;?php echo $d-&gt;from_user; ?&gt;"&gt;&lt;?php echo $d-&gt;from_user; ?&gt;&lt;/a&gt;
		&lt;?php echo $d-&gt;created_at; ?&gt; &lt;em&gt;from&lt;/em&gt; 

		&lt;?php echo html_entity_decode($d-&gt;source); ?&gt;
	&lt;/li&gt;
&lt;?php } ?&gt;
&lt;/ul&gt;</code></pre>
<p>This script outputs the tweets containing the word #carsonified along with profile images, timestamps and links to the client used.</p>
<p><img src="http://ryancarson.com/uploads/tweets.png" alt="Screenshot of We Love Typography's listing of tweets containing the hashtag #WLT" /><br />
	<a href="http://welovetypography.com/tweets/">We Love Typography</a> uses similar formatting to pull in tweets with the hashtag #WLT.</p>
<p>In the following source file I&#8217;m using a function for formatting the <em>created_at</em> field, so instead of &#8220;Fri, 14 Aug 2009 14:24:58 +0000&#8243; you will get something like &#8220;3 days, 17 hours ago&#8221;.
</p>
<p>Get the source for searching Twitter <a href="http://ryancarson.com/uploads/twitter_search.php.txt">here</a>. You&#8217;ll also need the <a href="http://ryancarson.com/uploads/time_passed.php.txt">file with the time_passed function</a> for this one.</p>
<h3>When the library just isn&#8217;t good enough</h3>
<p>The search API returns 50 results by default, which might not be convenient for everyone. The class php-twitter doesn&#8217;t set the results per page variable in the query strings, so let&#8217;s add that. You need to open the class.twitter.php file and replace line 844 with this:</p>
<p><code>function search( $terms=false, $rpp=false, $page=1, $callback=false )</code></p>
<p>Finally we add these three lines starting from line 854:</p>
<pre><code>if( $rpp )
$qs[] = 'rpp=' . $rpp;
$qs[] = 'page=' . $page;</code></pre>
<p>After these changes: </p>
<p><code>$data = $s->search('#carsonified', 5);</code></p>
<p>would only return the five latest results, and it would set the pagination to page one, whereas</p>
<p><code>$data = $s->search('#carsonified', 5, 2);</code></p>
<p>would set it to start from page two.</p>
<h3>Know your API</h3>
<p>The <a href="http://apiwiki.twitter.com/Twitter-API-Documentation">API Documentation</a> is pretty well done, so make sure to read it. Check out the methods like searching for current or daily trends or listing your followers and go make the next big Twitter app!</p>
<img src="http://carsonified.com/?ak_action=api_record_view&id=2980&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://carsonified.com/blog/dev/how-to-get-started-with-the-twitter-api/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
	</channel>
</rss>
