<?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>Robert Basic &#187; example</title>
	<atom:link href="http://robertbasic.com/blog/tag/example/feed/" rel="self" type="application/rss+xml" />
	<link>http://robertbasic.com/blog</link>
	<description>the magic of coding...</description>
	<lastBuildDate>Mon, 30 Jan 2012 13:15:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Bad Firebug!</title>
		<link>http://robertbasic.com/blog/bad-firebug/</link>
		<comments>http://robertbasic.com/blog/bad-firebug/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 21:21:30 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[escaping]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=833</guid>
		<description><![CDATA[We all know about Firebug, probably the best developer add-on out there, and how awesome it is and how many times it helped us debug some nasty Javascript code, mess around with CSS and HTML on-the-fly, to track the time load of every external page element our app loads&#8230; It&#8217;s so cool that it even [...]]]></description>
			<content:encoded><![CDATA[<p>We all know about <a class="zem_slink" href="http://www.getfirebug.com/" title="Firebug" rel="homepage">Firebug</a>, probably the best developer add-on out there, and how awesome it is and how many times it helped us debug some nasty Javascript code, mess around with CSS and HTML on-the-fly, to track the time load of every external page element our app loads&#8230; It&#8217;s so cool that it even has it&#8217;s own add-ons! (<a class="zem_slink" href="http://www.firephp.org/" title="FirePHP" rel="homepage">FirePHP</a>, <a class="zem_slink" href="http://developer.yahoo.com/yslow/" title="YSlow" rel="homepage">YSlow</a> and FireCookie). Really, it helps our developer lives to suck a bit less.</p>
<p><strong>Note: the following text is not about bashing other developers and their works, but to highlight the importance of proper input filtering. I myself have failed on this, several times.</strong></p>
<p><div id="attachment_844" class="wp-caption alignright" style="width: 250px"><a href="http://robertbasic.com/blog/wp-content/uploads/2009/12/omg_im_old.png"><img src="http://robertbasic.com/blog/wp-content/uploads/2009/12/omg_im_old-240x300.png" alt="OMG! I'm 1023 years old!" title="omg_im_old" class="size-medium wp-image-844" height="300" width="240"></a><p class="wp-caption-text">OMG! I'm 1023 years old!</p></div> Let&#8217;s go back to the part where we mess with the HTML by the means of this, may I say, application. You can add, hide, remove HTML elements, add, alter, remove, attributes from HTML elements&#8230; Adding, hiding, deleting &#8211; boring; altering &#8211; fun! I have this urge to try to break every form on every website I find. Not to do any harm, just to take a look how my fellow developer did his job and if I see anything that&#8217;s not right, I try to contact him to fix that, cause, y&#8217;know, I&#8217;m a nice person&#8230; Anyhow, I recently found some sites where all the textfields and textareas were filtered properly and no harm could be done &#8211; all my &#8220;hack&#8221; attempts were caught by their application. Nice. Oh, look, a select box! Right-click, inspect element, value=&#8221;xyz&#8221;, change that to value=&#8221;abc&#8221;, submit the form&#8230; and poof! A sexy SQL error. All that with the help of our li&#8217;l friend, Firebug. The elements where the user is required to provide some information &#8220;by hand&#8221; were processed correctly, but the select box was not.</p>
<p>OK, let&#8217;s take this one step further. On a site where the user can register an account and afterwards can edit his or hers profile. I register, go to the user panel, the usual stuff &#8211; change email, password, location, DoB (Date of Birth)&#8230; A quick inspection of the source &#8211; a hidden field &#8220;id&#8221; with a number in it. Hmm&#8230; Quickly, I register another account, note the &#8220;id&#8221; on that second account, go back to the first account, change the &#8220;id&#8221; of the first account to the &#8220;id&#8221; of the second account, change the DoB (just to see any actual information changing), click submit&#8230; &#8220;Your profile has been updated successfully.&#8221; Mine? Not really, the DoB is like it was in the first place&#8230; Go to the second account&#8230; Oh boy. I successfully changed the DoB of the second account, with my first account. Now, I haven&#8217;t seen their source code, but I can imagine what was going on. Something like this:</p>
<pre class="php" name="code">$id = (int)$_POST['id'];
$dob = $_POST['dob'];

$sql = "UPDATE users SET dob = '" . $dob . "' WHERE id = " . $id;
</pre>
<p>On the positive side, when I entered letters in that hidden field, I was told by the app that I haven&#8217;t filled all the fields correctly, which means they filtered even the hidden field, but skipped to check if that &#8220;id&#8221; is actually me.</p>
<p>OK, I know, the title is &#8220;Bad Firebug!&#8221; and the problems are actually about filtering user input, but I needed a catchy title to have your attention on Twitter :P</p>
<p>Even tho a field seems &#8220;unchangeable&#8221;, with a help of an awesome little app, it becomes changeable. And dangerous.</p>
<p>Filter input, escape output :)</p>
<p>P.S.: On the image above you can see my profile on a bulletin board, where I changed my year of birth from 1986 to 986 with Firebug. The years are in a select box; the lowest value is 1910. You can see my actual profile <a href="http://www.dizajnzona.com/forums/index.php?s=&amp;setlanguage=1&amp;langid=en&amp;showuser=12706&amp;cal_id=0">here</a>.</p>
<div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/445b648e-1e0c-40e5-812a-0e115d9334e7/" title="Reblog this post [with Zemanta]"><img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=445b648e-1e0c-40e5-812a-0e115d9334e7" alt="Reblog this post [with Zemanta]"></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/bad-firebug/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Chaining routes in Zend Framework</title>
		<link>http://robertbasic.com/blog/chaining-routes-in-zend-framework/</link>
		<comments>http://robertbasic.com/blog/chaining-routes-in-zend-framework/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 19:23:23 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[route]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=816</guid>
		<description><![CDATA[On a forum, there was a question today, about adding language &#8220;support&#8221; to the routes using Zend Framework. The guy wanted routes like /en/foo/bar or /de/baz. I wrote there an example for that using Zend_Router_Routes_Chain, so just posting that example here, too :) Image by shoothead via Flickr For what chains are for, is described [...]]]></description>
			<content:encoded><![CDATA[<p>On a forum, there was a question today, about adding language &#8220;support&#8221; to the routes using <a class="zem_slink" href="http://framework.zend.com/" title="Zend Framework" rel="homepage">Zend Framework</a>. The guy wanted routes like <code>/en/foo/bar</code> or <code>/de/baz</code>. I wrote there an example for that using <a href="http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.chain">Zend_Router_Routes_Chain</a>, so just posting that example here, too :)</p>
<div class="zemanta-img" style="margin: 1em; display: block;">
<div>
<dl style="width: 250px;" class="wp-caption alignright">
<dt class="wp-caption-dt"><a href="http://www.flickr.com/photos/66621443@N00/141114012"><img src="http://farm1.static.flickr.com/51/141114012_8cfe928eb5_m.jpg" alt="rusty chain" title="rusty chain" height="160" width="240"></a></dt>
<dd class="wp-caption-dd zemanta-img-attribution" style="font-size: 0.8em;">Image by <a href="http://www.flickr.com/photos/66621443@N00/141114012">shoothead</a> via Flickr</dd>
</dl>
</div>
</div>
<p>For what chains are for, is described in the manual, so I won&#8217;t be covering that :P</p>
<p>Basically, we&#8217;re prepending the language route to the other routes. This way, we have defined the route for the languages in one place only, plus, the other routes don&#8217;t have to worry about the language, too.</p>
<pre name="code" class="php">// this goes in the bootstrap class
public function _initRoutes()
{
    $this-&gt;bootstrap('FrontController');
    $this-&gt;_frontController = $this-&gt;getResource('FrontController');
    $router = $this-&gt;_frontController-&gt;getRouter();

    $langRoute = new Zend_Controller_Router_Route(
        ':lang/',
        array(
            'lang' =&gt; 'en'
        )
    );
    $contactRoute = new Zend_Controller_Router_Route_Static(
        'contact',
        array('controller'=&gt;'index', 'action'=&gt;'contact')
    );
    $defaultRoute = new Zend_Controller_Router_Route(
        ':controller/:action',
        array(
            'module'=&gt;'default',
            'controller'=&gt;'index',
            'action'=&gt;'index'
        )
    );

    $contactRoute = $langRoute-&gt;chain($contactRoute);
    $defaultRoute = $langRoute-&gt;chain($defaultRoute);

    $router-&gt;addRoute('langRoute', $langRoute);
    $router-&gt;addRoute('defaultRoute', $defaultRoute);
    $router-&gt;addRoute('contactRoute', $contactRoute);
}
</pre>
<p>Assuming that we have an Index controller, with actions index and contact and a Foo controller with actions index and bar, paired with the routes from the above example, we could do requests like:</p>
<pre>/ =&gt; /index/index/lang/en
/de =&gt; /index/index/lang/de
/sr/contact =&gt; /index/contact/lang/sr
/en/foo =&gt; /foo/index/lang/en
/fr/foo/bar =&gt; /foo/bar/lang/fr
</pre>
<p>Requesting a page like, e.g. <code>/de/baz</code>, would give us a 404 page, cause we don&#8217;t have a Baz controller.</p>
<p>HTH :)</p>
<p>Happy hacking!</p>
<div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/ea22a463-b7d7-42d3-bf7c-0fcb2e89785b/" title="Reblog this post [with Zemanta]"><img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=ea22a463-b7d7-42d3-bf7c-0fcb2e89785b" alt="Reblog this post [with Zemanta]"></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/chaining-routes-in-zend-framework/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Playing with Zend_Navigation and routes</title>
		<link>http://robertbasic.com/blog/playing-with-zend_navigation-and-routes/</link>
		<comments>http://robertbasic.com/blog/playing-with-zend_navigation-and-routes/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 17:05:20 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=762</guid>
		<description><![CDATA[Image by Aurelijus Valeiša via Flickr O hai. First things first — someone should slap me for being such a lazy blogger. Somehow I lost all the motivation I had in the beginning, but looks like it&#8217;s back now :) I finally had the time to play around with the latest Zend Framework version (v [...]]]></description>
			<content:encoded><![CDATA[<div class="zemanta-img" style="margin: 1em; display: block;">
<div>
<dl style="width: 250px;" class="wp-caption alignright">
<dt class="wp-caption-dt"><a href="http://www.flickr.com/photos/95124659@N00/2570224124"><img src="http://farm4.static.flickr.com/3031/2570224124_07e06c809f_m.jpg" alt="&quot;Zend Framework&quot; and &quot;PHP is th..." title="&quot;Zend Framework&quot; and &quot;PHP is th..." height="180" width="240"></a></dt>
<dd class="wp-caption-dd zemanta-img-attribution" style="font-size: 0.8em;">Image by <a href="http://www.flickr.com/photos/95124659@N00/2570224124">Aurelijus Valeiša</a> via Flickr</dd>
</dl>
</div>
</div>
<p>O hai. First things first — someone should slap me for being such a lazy blogger. Somehow I lost all the motivation I had in the beginning, but looks like it&#8217;s back now :) I finally had the time to play around with the latest <a class="zem_slink freebase/guid/9202a8c04000641f8000000000b66a0f" href="http://framework.zend.com/" title="Zend Framework" rel="homepage">Zend Framework</a> version (v 1.9 now). I managed to skip the whole 1.8.x version, so this whole Zend_Application stuff is quite new to me. I spent a few days poking around the manual and the code to make it work. And it works! Yey for me! And yey for <a href="http://twitter.com/akrabat">Rob Allen</a> for his post on <a href="http://akrabat.com/2009/07/08/bootstrapping-modules-in-zf-1-8/">Bootstrapping modules in ZF 1.8</a>!</p>
<p>Zend_Tool is an awesome tool. Creating a new project is like “zf create project project_name” :) And the new <a class="zem_slink" href="http://en.wikipedia.org/wiki/Bootstrapping" title="Bootstrapping" rel="wikipedia">bootstrapping</a> process with the Bootstrap class is somehow much clearer to me now&#8230; Anyways, lets skip to the code.</p>
<h2>The goal</h2>
<p>I wanted to set up routes in such way that when a user requests a page, all requests for non-existing controllers/modules are directed to a specific controller (not the error controller). In other words, if we have controllers IndexController, FooController and PageController, anything but http://example.com/index and http://example.com/foo is directed to the PageController. This can be useful for CMSs or blogs to make pretty links. Here&#8217;s where the <a href="http://twitter.com/jaspertandy/status/3205493310">Zend_Controller_Router_Route_Regex</a> stuff comes in:</p>
<pre class="php" name="code">$route = new Zend_Controller_Router_Route_Regex(
    '(?(?=^index$|^foo$)|([a-z0-9-_.]+))',
    array(
        'controller' =&gt; 'page',
        'action' =&gt; 'view',
        'slug' =&gt; null
    ),
    array(
        1 =&gt; 'slug',
    ),
    '%s'
    );

$router-&gt;addRoute('viewPage', $route);
</pre>
<p>Basically the regex does the following: if it&#8217;s index or foo don&#8217;t match anything, thus calling up those controllers, in any other case match what&#8217;s requested and pass it to the PageController&#8217;s viewAction as the slug parameter. The fourth parameter, the &#8216;%s&#8217;, is needed so that ZF can rebuild the route in components like the Zend_Navigation.</p>
<p>Now, when the PageController, viewAction get&#8217;s called up, we can check, for example, if a page with that slug exists (like, in a database). If it exists, show the content, otherwise call up a 404 page with the error controller. In this fancy and sexy way we can call up pages without passing ID&#8217;s or even letting the user know what part of the website is working on his request. He just request&#8217;s http://example.com/some_random_article and kaboom! he get&#8217;s the content :)</p>
<h2>Page navigation</h2>
<p>Oh the joy when I saw Zend_Navigation in the library! And it even includes view helpers to help us render links and menus and breadcrumbs! Yey! There are a <a href="http://blog.ekini.net/2009/05/25/zend-framework-making-the-built-in-breadcrumb-helper-work/">several</a> <a href="http://blog.ekini.net/2009/06/10/zend-framework-navigation-and-breadcrumbs-with-an-xml-file-in-zf-18/">blog posts</a> which go in details <a href="http://www.zendcasts.com/zend_navigation-dynamically-creating-a-menu-a-sitemap-and-breadcrumbs/2009/06/">about Zend_Navigation</a>, so I won&#8217;t be bothering with that. What I wanted to make with Zend_Navigation is to have a menu of all the pages rendered everywhere. Here&#8217;s where action helpers kick in. I made an action helper which makes up the structure of the links/pages. Something like this:</p>
<pre name="code" class="php">&lt;?php
class Zend_Controller_Action_Helper_LinkStructure extends
        Zend_Controller_Action_Helper_Abstract{
function direct(){
$structure = array(
    array(
         'label'=&gt;'Home page',
         'uri'=&gt;'/'
    ),
    array(
         'label'=&gt;'Articles',
         'uri'=&gt;'',
         'pages'=&gt;array(array(
                                  'label'=&gt;'Article 1',
                                  'uri'=&gt;'article_1'),
                              array(
                                  'label'=&gt;'Article 2',
                                  'uri'=&gt;'article_2'),
                         )
    )
);
return new Zend_Navigation($structure);
}
}
</pre>
<p>This is a simple example of the structure; I&#8217;m actually making it out from the database, with all the categories, subcategories and pages.</p>
<h2>Links everywhere</h2>
<p>To have this menu on all pages, we need to render it in the layout.phtml. Rendering is quite simple:</p>
<pre name="code" class="php">// somewhere in layout.phtml
&lt;?php echo $this-&gt;navigation()-&gt;menu(); ?&gt;
</pre>
<p>Of course, we need to pass the menu to the navigation helper somehow. To avoid doing <code>$this-&gt;navigation($this-&gt;_helper-&gt;linkStructure());</code> in all the controllers, we could do that once in the bootstrap (any other ways to make it happen?):</p>
<pre name="code" class="php">// in Bootstrap.php somewhere in the Bootstrap class
function _initView(){

        $view = new Zend_View();
        $view-&gt;doctype('XHTML1_STRICT');
        $view-&gt;headMeta()-&gt;appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8');

        // our helper is in app/controllers/helpers folder, but ZF doesn't know that, so tell him
        Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH.'/controllers/helpers');
        // now get the helper
        $linkStructure = Zend_Controller_Action_HelperBroker::getStaticHelper('LinkStructure');
        // and assign it to the navigation helper
        $view-&gt;navigation($linkStructure-&gt;direct());

        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
        $viewRenderer-&gt;setView($view);

        return $view;
}
</pre>
<p>There. Now we have our menu rendered on all pages. Sexy isn&#8217;t it? :)</p>
<p>That&#8217;s it for now. Hope someone will find this useful :) Now I gotta go, need to get ready for a punk rock concert tonight!</p>
<p>Happy hacking!</p>
<div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/900cdd04-8f9e-4bc3-9de1-03e0bd23457c/" title="Reblog this post [with Zemanta]"><img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=900cdd04-8f9e-4bc3-9de1-03e0bd23457c" alt="Reblog this post [with Zemanta]"></a><span class="zem-script more-related more-info pretty-attribution paragraph-reblog"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/playing-with-zend_navigation-and-routes/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>WordPress as CMS tutorial</title>
		<link>http://robertbasic.com/blog/wordpress-as-cms-tutorial/</link>
		<comments>http://robertbasic.com/blog/wordpress-as-cms-tutorial/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 11:00:36 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=644</guid>
		<description><![CDATA[WordPress is one of the best blogging platforms out there &#8212; if not the best. It&#8217;s very powerful, can be easily extended and modified. It&#8217;s documentation is very well written and, so far, had answer to all of my crazy questions :) You know what&#8217;s the best part of WordPress? With some knowledge of PHP [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://wordpress.org/">WordPress</a> is one of the best blogging platforms out there &#8212; if not the best. It&#8217;s very powerful, can be easily extended and modified. It&#8217;s <a href="http://codex.wordpress.org/Main_Page">documentation</a> is very well written and, so far, had answer to all of my crazy questions :)</p>
<p>You know what&#8217;s the best part of WordPress? With some knowledge of PHP and MySql, you can turn it into much more than just a blogging platform. After doing some HTML to WP work for <a href="http://twitter.com/styletime">Roger</a>, I thought of one way how could WordPress be transformed into a CMS. Note the &#8220;one way&#8221;. This is not the only way for doing this, and, most likely, not the best way.</p>
<p>I didn&#8217;t look much, but I think that there are some nice plugins out there that can do this. But, where&#8217;s the fun in the download, upload, activate process? Nowhere!</p>
<p>I will show you how to change your WordPress into a CMS and it really doesn&#8217;t take much coding to achieve this! The example presented here is <strong>simple</strong> and will have a static page for it&#8217;s home page, another static page for the &#8220;Portfolio&#8221; page and the blog. The home and portfolio page will have some of own content and both will include some content from other static pages. You all most likely know the blog part ;)</p>
<h2>Static pages</h2>
<p>Things you should know: each static page has it&#8217;s title, it&#8217;s slug or name (the thing that shows up in your browsers address bar: http://example.com/portfolio/ &#8211; right there, the portfolio is the slug!), has the parent attribute and the template attribute. The parent attribute is used when it&#8217;s needed to make one page a child of another, i.e. to show Page2 as a subpage of Page1. The template attribute is used when we want to apply some different layout and styling to a static page. Read more about <a href="http://codex.wordpress.org/Pages">static pages</a> and how to create your own <a href="http://codex.wordpress.org/Pages#Creating_Your_Own_Page_Templates">page templates</a>.</p>
<p><span id="more-644"></span></p>
<p>If you want to, you can download the theme I created for this tutorial from <a href="http://robertbasic.com/downloads/wpascms.zip">here</a> (it&#8217;s not a designers masterpiece, what did you expect?), or you can use any theme you want.</p>
<p>I hope you read the part on <a href="http://codex.wordpress.org/Pages#Creating_Your_Own_Page_Templates">creating page templates</a>, I really don&#8217;t feel like explaining the next part.</p>
<p>Create 3 new files in your template directory (if you&#8217;re using my theme, these files are already there): home.php, portfolio.php and blog.php. Contents of these files are:</p>
<pre name="code" class="php">
// home.php
&lt;?php
/*
Template Name: Home
*/
?&gt;

// portfolio.php
&lt;?php
/*
Template Name: Portfolio
*/
?&gt;

// blog.php
&lt;?php
/*
Template Name: Blog
*/

// Which page of the blog are we on?
$paged = get_query_var('paged');
query_posts('cat=-0&#038;paged='.$paged);

// make posts print only the first part with a link to rest of the post.
global $more;
$more = 0;

//load index to show blog
load_template(TEMPLATEPATH . '/index.php');
?&gt;
</pre>
<p>To understand the contents of the blog.php file, please take a look at <a href="http://codex.wordpress.org/Making_Your_Blog_Appear_in_a_Non-Root_Folder">this</a>.</p>
<p>Now, go to the dashboard, the Pages section and write 3 new static pages:</p>
<ul>
<li>Home, with the slug home, for the template choose Home from the drop-down list (it&#8217;s on the right side) and the parent leave as is (Main Page)</li>
<li>Portfolio, with the slug portfolio, for the template choose Portfolio</li>
<li>Blog, with the slug blog, for the template choose Blog</li>
</ul>
<p>You can add some content to the Home and Portfolio pages, but don&#8217;t add any to the Blog page.</p>
<h2>Organizing links</h2>
<p>Now, let&#8217;s make that when we are on http://example.com/ it shows us the Home page, instead of the Blog, and when on the http://example.com/blog/ to show us the blog!</p>
<p>Go to Settings->Reading and where it says &#8220;First page displays&#8221; choose &#8220;A static page&#8221;, and under the &#8220;Front page&#8221; drop-down choose &#8220;Home&#8221;.</p>
<p>Now, go to Settings->Permalinks and change the &#8220;Custom structure&#8221; to <code>/blog/%postname%/</code> or whatever is your preferred permalinks structure, but it must start with <code>/blog/</code>! If WordPress can&#8217;t write to your .htaccess file (I hope it can&#8217;t!), open it up in your editor and type the following (or similar, depends on your setup):</p>
<pre name="code" class="php">
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
&lt;/IfModule&gt;
</pre>
<p>The point is in the <code>RewriteBase</code>, with that we&#8217;re telling WP where to find the blog. On default setups, when http://example.com/ points to the blog, the RewriteBase is simply / but with the blog located at http://example.com/blog/ we need to change the RewriteBase. If all is well, we&#8217;re done with organizing the links.</p>
<p>While you&#8217;re still in the dashboard, write some new static pages with content. For the parent of these pages choose Portfolio and leave the template the default (the default page template is page.php).</p>
<h2>Time for coding!</h2>
<p>Here are two functions I wrote for retrieving content from static pages which will be then included in other static pages:</p>
<pre name="code" class="php">
// functions.php
&lt;?php

/**
* Gets last $number_of_subpages from their $parent_page
* If the &lt;!--more--&gt; tag is ignored ($ignore_more=true) returns the entire content of the subpages
*
* @param mixed $parent_page Contains either the slug of the parent page or it's ID
* @param integer $number_of_subpages Number of subpages to return
* @param boolean $ignore_more Whether to ignore the &lt;!--more--&gt; tag or not
* @return array Contents and titles of subapages
*/
function wpascms_get_subpages($parent_page='portfolio', $number_of_subpages=2, $ignore_more=false)
{
    global $wpdb;

    if(is_string($parent_page))
    {
        $parent_page_ID = wpascms_get_parent_page_ID($parent_page);
    }
    else
    {
        $parent_page_ID = $parent_page;
    }  

    if($number_of_subpages == 0)
    {
        $limit = '';
    }
    else
    {
        $limit = 'LIMIT 0, ' . $number_of_subpages;
    }
    // Get all subpages that are published and are childs of the given parent page
    // and order them by date in descending order (latest first)
    // also, if needed, limit to the latest $number_of_subpages
    $subpages = $wpdb-&gt;get_results("SELECT * FROM $wpdb-&gt;posts
                                    WHERE `post_parent` = '$parent_page_ID' AND `post_type` = 'page' AND `post_status` = 'publish'
                                    ORDER BY `post_date` DESC $limit");

    if(!$ignore_more)
    {
        foreach($subpages as $key=&gt;$subpage)
            if(strpos($subpage-&gt;post_content, '&lt;!--more--&gt;') !== false)
            {
                $short_content = explode('&lt;!--more--&gt;', $subpage-&gt;post_content, 2);
                $subpages[$key]-&gt;post_content = $short_content[0] . '&lt;a href="' . get_permalink($subpage-&gt;ID) . '"&gt;Read more...&lt;/a&gt;';
            }
        }
    }

    return $subpages;
}

function wpascms_get_parent_page_ID($parent_page)
{
    global $wpdb;

    $id = $wpdb-&gt;get_var($wpdb-&gt;prepare("SELECT ID FROM $wpdb-&gt;posts WHERE `post_name` = %s AND `post_type` = 'page' AND `post_status` = 'publish'", $parent_page));

    return $id;
}

?&gt;
</pre>
<p>The first function, <code>wpascms_get_subpages()</code> returns the given number of subpages from a specific parent page. By default it will break the content on the &lt;!&#8211;more&#8211;&gt; tag and append a &#8220;Read more&#8230;&#8221; link. The first parameter can be either a string containing the slug of the parent page, or the ID of the parent page. The second parameter is the number of subpages we want returned. If it&#8217;s zero, all subpages will be returned. The second function is merely a helper function, to get the id of the parent page based on it&#8217;s slug. To read more on querying the database, <a href="http://codex.wordpress.org/Function_Reference/wpdb_Class">read this page</a>.</p>
<p>Here&#8217;s how I&#8217;m calling this function on my example Home page:</p>
<pre name="code" class="php">
&lt;?php
/*
Template name: Home
*/

get_header();
?&gt;

    &lt;div id="home"&gt;
    &lt;?php if (have_posts()) : while (have_posts()) : the_post(); ?&gt;

        &lt;h2&gt;&lt;?php the_title(); ?&gt;&lt;/h2&gt;

        &lt;?php the_content('&lt;p class="serif"&gt;Read the rest of this page &raquo;&lt;/p&gt;'); ?&gt;

    &lt;?php endwhile; endif; ?&gt;
    &lt;/div&gt;&lt;!-- home --&gt;

    &lt;div id="latest_works"&gt;
    &lt;h1&gt;Recent work&lt;/h1&gt;
    &lt;?php $subpages = wpascms_get_subpages();
    if(count($subpages) &gt; 0):
        foreach($subpages as $row=&gt;$subpage):
        if($row%2 == 0)
        {
            $class = "left_work";
        }
        else
        {
            $class = "right_work";
        }
    ?&gt;
        &lt;div class="&lt;?php echo $class; ?&gt;"&gt;
            &lt;h2&gt;&lt;a href=&lt;?php echo get_permalink($subpage-&gt;ID); ?&gt;&gt;&lt;?php echo $subpage-&gt;post_title; ?&gt;&lt;/a&gt;&lt;/h2&gt;
                &lt;?php echo $subpage-&gt;post_content; ?&gt;
        &lt;/div&gt;
    &lt;?php
        endforeach;
    endif;
    ?&gt;
    &lt;/div&gt;&lt;!-- latest_works --&gt;

&lt;?php
get_footer();
?&gt;
</pre>
<p>In words: including the header, then showing any content of the home page. After that getting the subpages: by default, <code>wpascms_get_subpages()</code> is getting the newest 2 subpages of the portfolio page. I&#8217;m showing the content of the subpages in 2 columns. What we got with this? Add a new subpage to the portfolio and it will automagically show up on the left side column. In the end, including the footer.</p>
<p>Here&#8217;s another example from the portfolio page:</p>
<pre name="code" class="php">
&lt;?php
/*
Template name: Portfolio
*/

get_header();
?&gt;

    &lt;div id="portfolio"&gt;
    &lt;?php if (have_posts()) : while (have_posts()) : the_post(); ?&gt;

        &lt;h2&gt;&lt;?php the_title(); ?&gt;&lt;/h2&gt;

        &lt;?php the_content('&lt;p class="serif"&gt;Read the rest of this page &raquo;&lt;/p&gt;'); ?&gt;

    &lt;?php endwhile; endif; ?&gt;
    &lt;/div&gt;&lt;!-- home --&gt;

    &lt;div id="latest_works"&gt;

    &lt;?php $subpages = wpascms_get_subpages('portfolio', 0);
    if(count($subpages) &gt; 0):
        foreach($subpages as $row=&gt;$subpage):
    ?&gt;
        &lt;div class="work"&gt;
            &lt;h2&gt;&lt;a href=&lt;?php echo get_permalink($subpage-&gt;ID); ?&gt;&gt;&lt;?php echo $subpage-&gt;post_title; ?&gt;&lt;/a&gt;&lt;/h2&gt;
                &lt;?php echo $subpage-&gt;post_content; ?&gt;
        &lt;/div&gt;
    &lt;?php
        endforeach;
    endif;
    ?&gt;
    &lt;/div&gt;&lt;!-- latest_works --&gt;

&lt;?php
get_footer();
?&gt;
</pre>
<p>Same thing is happening here: including the header, showing the content of the portfolio page. Getting the subpages, but now all of the subpages that are childs of the portfolio page, and showing them one under the other.</p>
<p>All subpages can be viewed each on it&#8217;s own page, but that is just a plain ol&#8217; page.php file, so I&#8217;ll skip that.</p>
<h2>And now something completely different</h2>
<p>I made a screencast to show this in action. Please forgive me on my bad accent. This will just show how much I suck in speaking English. Oh, well.</p>
<div style="text-align:center;"><object width="400" height="304"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=3631432&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=F7E98C&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=3631432&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=F7E98C&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="304"></embed></object><br /><a href="http://vimeo.com/3631432">WordPress as CMS</a> from <a href="http://vimeo.com/robertbasic">Robert Basic</a> on <a href="http://vimeo.com">Vimeo</a>.</div>
<p>Don&#8217;t limit yourself to the existing plugins or waiting for one tutorial/example that will show how you can make everything. Don&#8217;t be afraid to get your hands dirty by hacking some code. It really doesn&#8217;t take too much to create magic with WordPress ;)</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/wordpress-as-cms-tutorial/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Trac on Ubuntu</title>
		<link>http://robertbasic.com/blog/trac-on-ubuntu/</link>
		<comments>http://robertbasic.com/blog/trac-on-ubuntu/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 13:26:32 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[lamp]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[trac]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=560</guid>
		<description><![CDATA[Today I was messing around with Trac, installing it and doing some basic configuration. While my dev machine gets updated, I want to share my process of installing Trac. What is Trac? As said on the Trac homepage: Trac is an enhanced wiki and issue tracking system for software development projects. It&#8217;s free, it&#8217;s open [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was messing around with <a href="http://trac.edgewall.org/">Trac</a>, installing it and doing some basic configuration. While my dev machine gets updated, I want to share my process of installing Trac.</p>
<h2>What is Trac?</h2>
<p>As said on the Trac homepage:</p>
<blockquote><p>Trac is an enhanced wiki and issue tracking system for software development projects.</p></blockquote>
<p>It&#8217;s free, it&#8217;s open source, it comes under the <a href="http://trac.edgewall.org/wiki/TracLicense">BSD license</a> and it&#8217;s really awesome. You can write a wiki with it, have a ticket system, connect it with SVN, so you can browse the sources from the browser and see all the commit messages, when was something changed, added&#8230; It can support one project, it can support multiple projects. It can be viewable/editable by anyone, or you can close it down for your little team&#8230;</p>
<p>Trac is big. It has lots of <a href="http://trac.edgewall.org/wiki/TracPlugins">plug-ins</a>, so you can extend and customize your Trac. I haven&#8217;t played with them yet, but as soon as I will, you&#8217;ll get <a href="http://feeds2.feedburner.com/robertbasic/blog/">notified</a> ;)</p>
<p>It&#8217;s written in <a href="http://python.org/">Python</a>. It can run on it&#8217;s own server, or it can run under Apache (where there are also <a href="http://trac.edgewall.org/wiki/TracInstall#WebServer">several options</a>). It can use SQlite, PostrgeSQL or MySQL databases. Currently it can connect only to SVN.</p>
<p>I&#8217;ll show you how to setup a basic Trac 0.11-dot-something-dot-something. It will run under Apache with <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a>, use a SQlite database, connect to the SVN repository and require user authentication.</p>
<p><span id="more-560"></span></p>
<h2>Installing Trac</h2>
<p>Before anything, I want to say that my machine where I installed Trac has LAMP and SVN <a href="http://robertbasic.com/blog/lamp-and-svn-on-ubuntu-8-10/">configured like this</a>. So, this post is kinda the next part of that post.</p>
<p>First, I installed a Python tool, called Easy Install. It&#8217;s here to make our installation process easier. Lovely. Go to <a href="http://pypi.python.org/pypi/setuptools/">http://pypi.python.org/pypi/setuptools/</a>, scroll down to the downloads section and choose a Python egg to download (match it to your currently installed Python version &#8212; I have Python 2.5 so I downloaded &#8220;setuptools-0.6c9-py2.5.egg&#8221;).</p>
<p>Fire up a console and type:</p>
<pre name="code" class="php">
sudo sh setuptools-0.6c9-py2.5.egg
</pre>
<p>Of course, you need to match this to your own setuptools file.</p>
<p>Next, type:</p>
<pre name="code" class="php">
sudo easy_install Trac
</pre>
<p>EasyInstall will now locate Trac and it&#8217;s dependencies, download and install them.</p>
<p>Download the mod_wsgi:</p>
<pre name="code" class="php">
sudo apt-get install libapache2-mod-wsgi
</pre>
<p>It will install and enable mod_wsgi. And, in my case, it only tried to restart Apache, but for an unknown reason it fails to do so. If that happens, just do a quick:</p>
<pre name="code" class="php">
sudo /etc/init.d/apache2 restart
</pre>
<p>If you want Subversion with your Trac, you&#8217;ll need the python-subversion package:</p>
<pre name="code" class="php">
sudo apt-get install python-subversion
</pre>
<p>If you have it already, it&#8217;ll just skip it. If you want SVN, but you don&#8217;t have this package, later on it will show an error message like: Unsupported version control system &#8220;svn&#8221;.</p>
<p>Now to make a folder for Trac, where it will keep all the Trac projects and stuff.</p>
<pre name="code" class="php">
sudo mkdir /var/trac /var/trac/sites /var/trac/eggs /var/trac/apache
sudo chown -R www-data /var/trac
</pre>
<p>Under <code>/var/trac/sites</code> will be the files for Trac projects. The <code>/var/trac/eggs</code> folder will be used as a cache folder for Python eggs. <code>/var/trac/apache</code> will hold a wsgi script file.</p>
<p>The wsgi script is actually a Python script, but with the .wsgi extension, used by mod_wsgi. With this script, Trac will be able to run as a WSGI application.<br />
File: <code>/var/trac/apache/trac.wsgi</code></p>
<pre name="code" class="php">
import sys
sys.stdout = sys.stderr

import os
os.environ['TRAC_ENV_PARENT_DIR'] = '/var/trac/sites'
os.environ['PYTHON_EGG_CACHE'] = '/var/trac/eggs'

import trac.web.main

application = trac.web.main.dispatch_request
</pre>
<p>With this kind of script, one single Trac installation will be able to manage multiple projects (you can see <a href="http://code.google.com/p/modwsgi/wiki/IntegrationWithTrac">here</a> some other scripts).</p>
<p>Configure Apache, add this to your <code>httpd.conf</code> file:</p>
<pre name="code" class="php">
WSGIScriptAlias /trac /var/trac/apache/trac.wsgi

&lt;Directory /var/trac/apache&gt;
    WSGIApplicationGroup %{GLOBAL}
    Order deny,allow
    Allow from all
&lt;/Directory&gt;
</pre>
<p>Restart Apache:</p>
<pre name="code" class="php">
sudo /etc/init.d/apache2 restart
</pre>
<p>If you go to <a href="http://localhost/trac/">http://localhost/trac/</a> in your browser, you should see an empty list of Available Projects. It&#8217;s empty, cause we haven&#8217;t added any project yet.</p>
<p>Now, let&#8217;s asume that we have a project called &#8220;testProject&#8221; with it&#8217;s source located in <code>/var/www/testProject</code> and a SVN repo located in <code>/var/svn/repos/testProject</code>. I&#8217;ll show how to add that project to Trac.</p>
<p>In console type:</p>
<pre name="code" class="php">
sudo trac-admin /var/trac/sites/testProject initenv
</pre>
<p>Note that you need to provide the full path to <code>/var/trac/sites</code>, cause it will create a Trac project in the current folder you&#8217;re in.</p>
<p>It will ask you now a few things:</p>
<ul>
<li>Project Name &#8212; the name of the project, e.g. &#8220;Trac testing project&#8221;</li>
<li>Database connection string &#8212; leave it empty, and it will use SQlite</li>
<li>Repository type &#8212; leave it empty, and it will use SVN</li>
<li>Path to repository &#8212; path to the project repo, e.g. <code>/var/svn/repos/testProject</code>
</ul>
<p>It will start to print out a bunch of lines, about what is it doing. In the end you&#8217;ll get a message like &#8220;Project environment for &#8216;testProject&#8217; created.&#8221; and a few more lines. One more thing. We need to add the whole project to www-data user, so it can manage the files:</p>
<pre name="code" class="php">
sudo chown -R www-data /var/trac/sites/testProject
</pre>
<p>If you direct your browser again to <a href="http://localhost/trac/">http://localhost/trac/</a>, you will now see a link for the <code>testProject</code>. Click it. There, a fully working basic Trac environment for your project. A wiki, a ticket/bug tracking system, a repo browser in only a few minutes. How cool is that? Very.</p>
<p>This Trac environment can now be accessible by everyone. If we do not want that, we need to add this to the <code>httdp.conf</code> file:</p>
<pre name="code" class="php">
&lt;Location /trac&gt;
    AuthType Basic
    AuthName "Trac login"
    AuthUserFile /var/trac/.htpasswd
    Require valid-user
&lt;/Location&gt;
</pre>
<p>Create the <code>.htpasswd</code> file:</p>
<pre name="code" class="php">
sudo htpasswd -bcm /var/trac/.htpasswd your_username your_password
</pre>
<p>All set. You&#8217;ll now have to login to Trac to be able to work on it. As I&#8217;m the big boss on my localhost, I gave myself some super-power privileges for Trac: TRAC_ADMIN. It&#8217;s like root on *NIX.</p>
<pre name="code" class="php">
sudo trac-admin /var/trac/sites/testProject permission add robert TRAC_ADMIN
</pre>
<p>Read more about <a href="http://trac.edgewall.org/wiki/TracPermissions">privileges</a>.</p>
<p>That would be it. With this kind of setup, for now, it&#8217;s working perfectly for me. For Trac that&#8217;s available from the whole Internet, more security measures are needed, but this is only on localhost, so this is enough for me.</p>
<p>Comments, thoughts, ideas? </p>
<p>Happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/trac-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Login example with Zend_Auth</title>
		<link>http://robertbasic.com/blog/login-example-with-zend_auth/</link>
		<comments>http://robertbasic.com/blog/login-example-with-zend_auth/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 20:25:38 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[authenticate]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=505</guid>
		<description><![CDATA[Happy New Year! Hope everyone had a blast for New Year&#8217;s Eve and managed to get some rest :) This is my first working day for this year. I&#8217;m still kinda lazy and sleepy. And I wanna eat something all the time. Damn you candies!!! So, here&#8217;s what I&#8217;m going to do: authenticate an user [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Happy New Year!</strong> Hope everyone had a blast for New Year&#8217;s Eve and managed to get some rest :) This is my first working day for this year. I&#8217;m still kinda lazy and sleepy. And I wanna eat something all the time. Damn you candies!!!</p>
<p>So, here&#8217;s what I&#8217;m going to do: authenticate an user against a database table using Zend Framework&#8217;s Zend_Auth component. It&#8217;s really a piece of cake. You can see a working example here: <a href="http://robertbasic.com/dev/login/">http://robertbasic.com/dev/login/</a>. Feel free to test it and report any misbehavior down in the <a href="http://robertbasic.com/blog/login-example-with-zend_authlogin-example-with-zend_auth/#comments">comments</a>. In the codes below all paths, class names, actions, etc. will be as are in the example, so you probably will need to changed those according to your setup.</p>
<h2>Preparation</h2>
<p>Because I&#8217;m gonna use a database, be sure to have set the default database adapter in the bootstrap file, I have it setup like this:</p>
<pre name="code" class="php">
$config = new Zend_Config_Ini('../application/dev/config/db_config.ini', 'offline');
$registry = Zend_Registry::getInstance();
$registry-&gt;set('db_config',$config);
$db_config = Zend_Registry::get('db_config');
$db = Zend_Db::factory($db_config-&gt;db);
Zend_Db_Table::setDefaultAdapter($db);
</pre>
<p>I&#8217;ll need it later in the code. The table structure is as follows:</p>
<pre name="code" class="sql">
--
-- Table structure for table `zendLogin`
--

CREATE TABLE `zendLogin` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL,
  `password` varchar(32) NOT NULL,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
</pre>
<p><span id="more-505"></span></p>
<h2>The login controller</h2>
<p>The magic happens in the <code>LoginController</code>. It has two actions: <code>indexAction</code> and <code>logoutAction</code>. The <code>indexAction</code> will take care of showing the login form and processing the login process. The <code>logoutAction</code> will just logout the user. You would never figure out that one on your own, right?</p>
<p>Now, let&#8217;s get to the fun part &#8212; the code:</p>
<pre name="code" class="php">
&lt;?php
class Dev_LoginController extends Zend_Controller_Action
{
    public function indexAction()
    {
        // If we're already logged in, just redirect
        if(Zend_Auth::getInstance()-&gt;hasIdentity())
        {
            $this-&gt;_redirect('dev/secured/index');
        }

        $request = $this-&gt;getRequest();
        $loginForm = $this-&gt;getLoginForm();

        $errorMessage = "";
</pre>
<p>Not much happening here: if the user is already logged in, I don&#8217;t want him at the login form, so just redirect him somewhere else; most likely to a home page or a control panel&#8217;s index page.</p>
<p>The <code>Zend_Auth</code> implements the Singleton pattern &#8212; if you&#8217;re not familiar with it read <a href="http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction">http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction</a> and <a href="http://www.php.net/manual/en/language.oop5.patterns.php">http://www.php.net/manual/en/language.oop5.patterns.php</a> (at php.net scroll down to the example #2).</p>
<p>So, I&#8217;m just asking the <code>Zend_Auth</code> does it have an user identity stored in it; the identity gets stored only upon successful log in. I&#8217;m also getting the request object. The <code>getLoginForm()</code> is a function that I wrote for assembling the login form and is a part of the <code>LoginController</code>, I&#8217;ll show it&#8217;s code later.</p>
<pre name="code" class="php">
if($request-&gt;isPost())
{
    if($loginForm-&gt;isValid($request-&gt;getPost()))
    {
        // get the username and password from the form
        $username = $loginForm-&gt;getValue('username');
        $password = $loginForm-&gt;getValue('password');
</pre>
<p>This doesn&#8217;t needs a lot of explanation: if it&#8217;s a post request, it means the form is submitted. If the submitted data is valid, just get the wanted values from the form.</p>
<pre name="code" class="php">
        $dbAdapter = Zend_Db_Table::getDefaultAdapter();
        $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);

        $authAdapter-&gt;setTableName('zendLogin')
                    -&gt;setIdentityColumn('username')
                    -&gt;setCredentialColumn('password')
                    -&gt;setCredentialTreatment('MD5(?)');
</pre>
<p>Here I&#8217;m getting the default database adapter, so I know whit which database I&#8217;m working with. Then I&#8217;m creating an adapter for Zend_Auth, which is used for authentication; the docs give good explanation on the adapter, read it here: <a href="http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction.adapters">http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction.adapters</a>.</p>
<p>Next, I&#8217;m telling the authentication adapter which table to use from the database, and which columns from that table. Also, I&#8217;m telling it how to treat the credentials &#8212; the passwords are stored as MD5 hashes, so the submitted passwords will first be MD5ed and then checked.</p>
<pre name="code" class="php">
        // pass to the adapter the submitted username and password
        $authAdapter-&gt;setIdentity($username)
                    -&gt;setCredential($password);

        $auth = Zend_Auth::getInstance();
        $result = $auth-&gt;authenticate($authAdapter);
</pre>
<p>I&#8217;m passing to the adapter the user submitted username and password, and then trying to authenticate with that username and password.</p>
<pre name="code" class="php">
        // is the user a valid one?
        if($result-&gt;isValid())
        {
            // get all info about this user from the login table
            // ommit only the password, we don't need that
            $userInfo = $authAdapter-&gt;getResultRowObject(null, 'password');

            // the default storage is a session with namespace Zend_Auth
            $authStorage = $auth-&gt;getStorage();
            $authStorage-&gt;write($userInfo);

            $this-&gt;_redirect('dev/secured/index');
        }
</pre>
<p>If the user is successfully authenticated, get all information about him from the table (if any), like the real name, E-mail, etc. I&#8217;m leaving out the password, I don&#8217;t need that. Next I&#8217;m getting the <code>Zend_Auth</code>&#8216;s <a href="http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction.persistence.default">default storage</a> and storing in it the user information. In the end I&#8217;m redirecting it where I want it.</p>
<pre name="code" class="php">
else
{
    $errorMessage = "Wrong username or password provided. Please try again.";
}
}
}
$this-&gt;view-&gt;errorMessage = $errorMessage;
$this-&gt;view-&gt;loginForm = $loginForm;
}
</pre>
<p>And this is the end of the <code>indexAction</code>. I know I could take the correct message from <code>$result</code> with <code>getMessages()</code>, but I like more this kind of message, where I&#8217;m not telling the user which part did he got wrong.</p>
<pre name="code" class="php">
public function logoutAction()
{
    // clear everything - session is cleared also!
    Zend_Auth::getInstance()-&gt;clearIdentity();
    $this-&gt;_redirect('dev/login/index');
}
</pre>
<p>This is the <code>logoutAction</code>. I&#8217;m clearing the identity from <code>Zend_Auth</code>, which is also clearing all data from the <code>Zend_Auth</code> session namespace. And, of course, redirecting back to the login form.</p>
<pre name="code" class="php">
protected function getLoginForm()
{
    $username = new Zend_Form_Element_Text('username');
    $username-&gt;setLabel('Username:')
            -&gt;setRequired(true);

    $password = new Zend_Form_Element_Password('password');
    $password-&gt;setLabel('Password:')
            -&gt;setRequired(true);

    $submit = new Zend_Form_Element_Submit('login');
    $submit-&gt;setLabel('Login');

    $loginForm = new Zend_Form();
    $loginForm-&gt;setAction('/dev/login/index/')
            -&gt;setMethod('post')
            -&gt;addElement($username)
            -&gt;addElement($password)
            -&gt;addElement($submit);

    return $loginForm;
}
</pre>
<p>As promised, here&#8217;s the code for <code>getLoginForm</code> function. That&#8217;s the whole <code>LoginController</code> code, not really a rocket science :) Sorry if it&#8217;s a bit hard to keep up with the code, I needed it to break it up in smaller pieces&#8230;</p>
<p>And here&#8217;s the view script for the <code>indexAction</code>.</p>
<pre name="code" class="php">
&lt;h2&gt;Zend_Login example&lt;/h2&gt;

&lt;p&gt;
Hello! This is an example of authenticating users with the Zend Framework...
&lt;/p&gt;

&lt;p&gt;Please login to proceed.&lt;/p&gt;

&lt;?php if($this-&gt;errorMessage != ""): ?&gt;
&lt;p class="error"&gt;&lt;?= $this-&gt;errorMessage; ?&gt;&lt;/p&gt;
&lt;?php endif; ?&gt;

&lt;?= $this-&gt;loginForm; ?&gt;
</pre>
<h2>Other controllers</h2>
<p>Couldn&#8217;t come up with a better subtitle :(</p>
<p>Here&#8217;s an example how to require the user to log in to see the page: in the <code>init()</code> method ask <code>Zend_Auth</code> is the user logged in, and if not redirect him to the login form. This way the user will have to log in to the &#8220;whole controller&#8221;. Implement the same only to the <code>indexAction</code>, and the user will have to only log in to see the index page; he&#8217;ll be able to access another page without logging in. </p>
<pre name="code" class="php">
class Dev_SecuredController extends Zend_Controller_Action
{
    function init()
    {
        // if not logged in, redirect to login form
        if(!Zend_Auth::getInstance()-&gt;hasIdentity())
        {
            $this-&gt;_redirect('dev/login/index');
        }
    }

    public function indexAction()
    {
        // get the user info from the storage (session)
        $userInfo = Zend_Auth::getInstance()-&gt;getStorage()-&gt;read();

        $this-&gt;view-&gt;username = $userInfo-&gt;username;
        $this-&gt;view-&gt;name = $userInfo-&gt;name;
        $this-&gt;view-&gt;email = $userInfo-&gt;email;
    }

    public function anotherAction()
    {
    }
}
</pre>
<p>I&#8217;m also reading out the user information from the <code>Zend_Auth</code>&#8216;s storage, that I have stored there during the log in process.</p>
<p>So there. A fully working login system, which can be setup in a really short time.</p>
<p><strong>Update: If you want, you can get an example source code from here: <a href="http://robertbasic.com/downloads/zendLogin.zip">zendLogin.zip</a> ~8kB</strong></p>
<p>Happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/login-example-with-zend_auth/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Styling the default Zend_Form layout</title>
		<link>http://robertbasic.com/blog/styling-the-default-zend_form-layout/</link>
		<comments>http://robertbasic.com/blog/styling-the-default-zend_form-layout/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 22:17:21 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[styling]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=458</guid>
		<description><![CDATA[Here&#8217;s an example for styling Zend_Form&#8216;s default layout. The default layout is using definition lists. While there&#8217;s an option for changing the default layout, the wrapper tags and stuff, I see no reason for it. Create the form, add some CSS and your good to go :) Note: Be sure to provide a Document Type [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s an example for styling <a href="http://framework.zend.com/manual/en/zend.form.html">Zend_Form</a>&#8216;s default layout. The default layout is using <a href="http://w3schools.com/tags/tag_dl.asp">definition lists</a>. While there&#8217;s an option for changing the default layout, the wrapper tags and stuff, I see no reason for it. Create the form, add some CSS and your good to go :)</p>
<p>Note: Be sure to provide a Document Type in your view scripts like this:</p>
<pre name="code" class="php">
&lt;?= $this-&gt;doctype('XHTML1_STRICT') ?&gt;
</pre>
<p>because when the form is generated, ZF is looking at the doctype to see how to create the form elements. Forgetting the doctype will probably generate invalid markup. I learned the hard way. Don&#8217;t do the same mistake, k? :)</p>
<h2>The generated markup</h2>
<p>So, here&#8217;s what Zend_Form makes for us (this markup is after submitting the form, but whit generated error, to show the error markup, too):</p>
<pre name="code" class="php">
&lt;form enctype="application/x-www-form-urlencoded" method="post" action=""&gt;
&lt;dl class="zend_form"&gt;
    &lt;dt&gt;
        &lt;label for="input1" class="required"&gt;Input field #1:&lt;/label&gt;
    &lt;/dt&gt;
    &lt;dd&gt;
        &lt;input type="text" name="input1" id="input1" value="" /&gt;
        &lt;ul class="errors"&gt;
            &lt;li&gt;Value is empty, but a non-empty value is required&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p class="description"&gt;Description? Yes, please.&lt;/p&gt;
    &lt;/dd&gt;
    &lt;dt&gt;
        &nbsp;
    &lt;/dt&gt;
    &lt;dd&gt;
        &lt;input type="submit" name="submit" id="submit" value="Submit form" /&gt;
    &lt;/dd&gt;
&lt;/dl&gt;
&lt;/form&gt;
</pre>
<p>The PHP code which generates this form (without the error, of course) goes like this:</p>
<pre name="code" class="php">
$input1 = new Zend_Form_Element_Text('input1');
$input1-&gt;setLabel('Input field #1:')
          -&gt;setDescription('Description? Yes, please.')
          -&gt;setRequired(true);

$submit = new Zend_Form_Element_Submit('submit');
$submit-&gt;setLabel('Submit form')

$form = new Zend_Form();
$form-&gt;setMethod('post')
       -&gt;addElement($input1)
       -&gt;addElement($submit);
</pre>
<div id="attachment_466" class="wp-caption alignright" style="width: 160px"><a href="http://robertbasic.com/blog/wp-content/uploads/2008/12/zendformnocss.gif"><img src="http://robertbasic.com/blog/wp-content/uploads/2008/12/zendformnocss-150x150.gif" alt="Default Zend_Form layout with no CSS" title="zendformnocss" width="150" height="150" class="size-thumbnail wp-image-466" /></a><p class="wp-caption-text">Default Zend_Form layout with no CSS</p></div>
<p>Now, the generated form looks kinda good with no styling (which is good, if some maniac comes to visit with CSS support disabled).</p>
<p>OK, I lie: there&#8217;s a minimum of CSS for setting the background to white and the width to 460 pixels.</p>
<p>As you can see I&#8217;ve shortened the HTML and the PHP in the example codes&#8230;</p>
<h2>The styling</h2>
<p>I like my forms a bit different: form elements and their labels side by side with element descriptions and eventual errors showing up under the element. Here&#8217;s the CSS to achieve this:</p>
<pre name="code" class="css">
.zend_form{
background:#fff;
width:460px;
margin:5px auto;
padding:0;
overflow:auto;
}

.zend_form dt{
padding:0;
clear:both;
width:30%;
float:left;
text-align:right;
margin:5px 5px 5px 0;
}

.zend_form dd{
padding:0;
float:left;
width:68%;
margin:5px 2px 5px 0;
}

.zend_form p{
padding:0;
margin:0;
}

.zend_form input, .zend_form textarea{
margin:0 0 2px 0;
padding:0;
}

.submit{
float:right;
}

.required:before{content:'* '}

.optional:before{content:'+ '}
</pre>
<div id="attachment_484" class="wp-caption alignright" style="width: 160px"><a href="http://robertbasic.com/blog/wp-content/uploads/2008/12/zendform1.gif"><img src="http://robertbasic.com/blog/wp-content/uploads/2008/12/zendform1-150x150.gif" alt="Default Zend_Form layout with CSS" title="zendform1" width="150" height="150" class="size-thumbnail wp-image-484" /></a><p class="wp-caption-text">Default Zend_Form layout with CSS</p></div>
<p>Of course, this CSS takes care only of the layout; things like font types and sizes, colors, borders, backgrounds, etc. are not essential for this.</p>
<p>So, with this CSS applied to the generated Zend_Form, you can see on the image what will come up. And you know what&#8217;s the best part? It&#8217;s good for Firefox, Internet Explorer 6, Chrome and Opera, both under Windows and GNU/Linux (sorry, not tested for Internet Explorer 7 and Safari, but they should play along as well).</p>
<p>I almost forgot: I added a class=&#8221;submit&#8221; to the submit button, to be able to float it right. I first tried to do that with input[type=submit], but IE doesn&#8217;t know that, and as I wanted to make a styling that looks (almost) the same in all browsers with no hacks, I decided to add the class attribute.</p>
<p>So there, this little CSS code snippet should get you started with styling your Zend Form&#8217;s.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/styling-the-default-zend_form-layout/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Data filtering with PHP&#8217;s Filter extension</title>
		<link>http://robertbasic.com/blog/data-filtering-with-php-filter-extension/</link>
		<comments>http://robertbasic.com/blog/data-filtering-with-php-filter-extension/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 17:14:05 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[input]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[secure]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=439</guid>
		<description><![CDATA[Today I was catching up on feeds and one of the articles lead me to GoPHP5.org, where I spent some time lurking. In the FAQ section of that site one sentence made me curios: The Filter extension is a new security component in PHP. Filter extension? Maybe it&#8217;s nothing new for some of you, but [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was catching up on feeds and one of the articles lead me to <a href="http://www.gophp5.org/">GoPHP5.org</a>, where I spent some time lurking. In the <a href="http://www.gophp5.org/faq#n7">FAQ section</a> of that site one sentence made me curios:</p>
<blockquote><p>The Filter extension is a new security component in PHP.</p></blockquote>
<p>Filter extension? Maybe it&#8217;s nothing new for some of you, but it is for me. I&#8217;ve never heard of it before. So I quickly hopped over to PHP.net and the <a href="http://www.php.net/manual/en/book.filter.php">Filter chapter</a> of the manual.</p>
<p>The filter extension is an extension that comes by default in PHP 5.2. It is here to help us to &#8220;validate and filter data that comes from insecure sources, such as user input&#8221;. It can validate integers, booleans, floats, regular expressions, URLs, E-Mails and IPs. It can sanitize strings, integers, floats, URLs, E-Mails&#8230;</p>
<h2>Examples</h2>
<p>Here are some examples about what this extension is capable of. Lets assume that we get some data from a form with POST method. The 3 input fields are name, email and age (I&#8217;m not creating a real validator, but var_dump-ing the results of the filtering, to show what filter gives what kind of output). </p>
<pre name="code" class="php">
// $_POST['name'] = "Robert <b>hello</b>";
var_dump(filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING));
// Output: string(12) "Robert hello"

// $_POST['email'] = "mail@example.com";
var_dump(filter_input(INPUT_POST, 'name', FILTER_VALIDATE_EMAIL));
// Output: string(16) "mail@example.com"

// $_POST['age'] = "22";
var_dump(filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT,
                        array('options' =&gt; array('min_range' =&gt; 18,
                                                'max_range' =&gt; 28)
                        )));
// Output: int(22)
</pre>
<p>With the first filter I&#8217;m using the <code>FILTER_SANITIZE_STRING</code> which strips down all tags and unwanted characters from our string. The second filter validates the provided E-mail address: pass it a malformed E-mail address and it will result with a boolean <code>false</code>. The third filter validates the age: it must be an integer and in the range between 18 and 28 (the min and max ranges are optional, I added them just for the example).</p>
<p>Besides input filtering it can filter variables, too:</p>
<pre name="code" class="php">
$string = "Some funky string with <b>html</b> code and 'quotes'";
var_dump(filter_var($string, FILTER_SANITIZE_STRING));
// Output: string(53) "Some funky string with html code and 'quotes'"
// NOTE: the single quotes in the output are encoded as &amp;#39;

var_dump(filter_var($string, FILTER_SANITIZE_MAGIC_QUOTES));
// Output: string(54) "Some funky string with html code and \'quotes\'"
// NOTE: the <b></b> html tags are NOT stripped in the output

var_dump(filter_var($string, FILTER_SANITIZE_ENCODED));
// Output: string(80) "Some%20funky%20string%20with%20%3Cb%3Ehtml%3C%2Fb%3E%20code%20and%20%27quotes%27"
</pre>
<p>Play around with it, get familiar, cause this is one nice extension that will help you make more secure web sites and web apps.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/data-filtering-with-php-filter-extension/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>MyUrl view helper for Zend Framework</title>
		<link>http://robertbasic.com/blog/myurl-view-helper-for-zend-framework/</link>
		<comments>http://robertbasic.com/blog/myurl-view-helper-for-zend-framework/#comments</comments>
		<pubDate>Tue, 02 Dec 2008 18:02:48 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[helper]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=427</guid>
		<description><![CDATA[I started writing some boring introduction but I&#8217;ll just skip to the point. The problem Zend Framework&#8217;s built in URL view helper &#8212; Zend_View_Helper_Url &#8212; is discarding the query string of the URL, thus breaking some links. Example: If I&#8217;m on a page like: http://project/foo/bar/?param1=value1 and in the bar.phtml I use the Url helper like [...]]]></description>
			<content:encoded><![CDATA[<p>I started writing some boring introduction but I&#8217;ll just skip to the point.</p>
<h2>The problem</h2>
<p>Zend Framework&#8217;s built in URL view helper &#8212; <code>Zend_View_Helper_Url</code> &#8212; is discarding the query string of the URL, thus breaking some links.</p>
<p>Example: If I&#8217;m on a page like:<br />
<code>http://project/foo/bar/?param1=value1</code><br />
and in the bar.phtml I use the Url helper like this:</p>
<pre name="code" class="php">
&lt;?= $this-&gt;url(array('param2' =&gt; 'value2')); ?&gt;
</pre>
<p>I expect this:<br />
<code>http://project/foo/bar/param2/value2/?param1=value1</code><br />
or something similar to this. This would be just perfect:<br />
<code>http://project/foo/bar/param1/value1/param2/value2</code><br />
But no, it gives:<br />
<code>http://project/foo/bar/param2/value2/</code></p>
<h2>The solution</h2>
<p>After working on several workarounds, currently this is the best one I can think of &#8212; take the link that is created by the built-in Url helper and add the query string on that link:</p>
<pre name="code" class="php">
&lt;?php

// Usage:
// &lt;?= $this-&gt;myUrl($this-&gt;url(array('param2' =&gt; 'value2'))); ?&gt;
// Output:
// http://project/controller/action/param2/value2/?param1=value1
class Zend_View_Helper_MyUrl
{
    public function myUrl(&#038;$url, &#038;$toAdd = array())
    {
        $requestUri = Zend_Controller_Front::getInstance()-&gt;getRequest()-&gt;getRequestUri();
        $query = parse_url($requestUri, PHP_URL_QUERY);
        if($query == '')
        {
            return $url;
        }
        else if(empty($toAdd))
        {
            return $url . '/?' . $query;
        }
        else
        {
            $toAdd = (array)$toAdd;
            $query = explode("&#038;", $query);

            $add = '/?';

            foreach($toAdd as $addPart)
            {
                foreach($query as $queryPart)
                {
                    if(strpos($queryPart, $addPart) !== False)
                    {
                        $add .= '&#038;' . $queryPart;
                    }
                }
            }
            return $url . $add;
        }
    }
}
</pre>
<p>The second parameter, <code>$toAdd</code>, should be an array of parameters that we want to add to the URL. Say, if I have a query string like:<br />
<code>?param1=value1&#038;someotherparam=anditsvalue</code><br />
but want only to add the <code>param1=value1</code> to the URL, I would pass &#8220;param1&#8221; as the second parameter. Not passing anything as the second parameter will result in adding the complete query string to the URL.</p>
<p>This is an ugly hack to make ugly links work, but it works. Thoughts?</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/myurl-view-helper-for-zend-framework/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>A Zend_Captcha example</title>
		<link>http://robertbasic.com/blog/a-zend-captcha-example/</link>
		<comments>http://robertbasic.com/blog/a-zend-captcha-example/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 20:27:46 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://robertbasic.com/blog/?p=346</guid>
		<description><![CDATA[Update: I made an error in the example code, regarding the CAPTCHA image URL. I&#8217;m sorry for any troubles caused by this mistake. Update #2: Here&#8217;s an example of using Zend_Captcha without the whole Zend Framework stuff. Update #3: There was an unintentional error in the captchaAction() method, Adam warned me about it in the [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update: I made an error in the example code, regarding the CAPTCHA image URL. I&#8217;m sorry for any troubles caused by this mistake.</strong></p>
<p><strong>Update #2: <a href="http://sankhomallik.com/2008/12/17/tutorial-using-zend_captcha_image/">Here&#8217;s an example</a> of using Zend_Captcha without the whole Zend Framework stuff.</strong></p>
<p><strong>Update #3: There was an unintentional error in the captchaAction() method, Adam warned me about it in the comments. The error is fixed now. Thanks Adam.</strong></p>
<p>OK, this was a bit tricky and I found no examples about it, so I thought to blog it. I&#8217;ll just show a quick example how to implement Zend_Captcha into a Zend_Form, may be useful for someone. There are several CAPTCHA types in ZF, like the Image, Figlet and Dumb. I use Image.</p>
<p>First of all, we&#8217;ll use sessions, so we need to change the bootstrap file a little:</p>
<pre name="code" class="php">
// Put this line somewhere after the Zend_Loader::registerAutoload(); line
Zend_Session::start();
</pre>
<p>We need to start the session to use it, putting it close to the top will assure that there will be no &#8220;Headers already sent by&#8230;&#8221; errors caused by a wrongly placed session start.</p>
<p>Next we need a folder which has a 777 permission on it (Windows users, you can skip this&#8230; Or start using GNU/Linux) where we will put our captcha images for a while&#8230; This folder must be in the public folder somewhere. So create one.</p>
<p>How does this work? When a captcha is generated, it generates a unique ID (e.g. 539e517b0c0f4e32ef634dae92f07f77) and the word on the image. That unique ID is used for the file name of the image and for the session namespace (the namespace is like: Zend_Form_Captcha_uniqueId), so it knows which image belongs to which session. Also, the generated word is placed inside it&#8217;s own session. That ID is placed on the form in a hidden field, so when the submission is received, we can access the ID and recreate the correct session namespace and access the data in it: the word on the image.</p>
<p>Awesome. Now, to the fun part. I use the <code>Zend_Form_Element_Captcha</code> class, so no additional fooling around is needed to put the captcha in the form. Here&#8217;s the code:</p>
<pre name="code" class="php">
public function indexAction()
{
// Our form object...
$form = new Zend_Form();
// And here's our captcha object...
$captcha = new Zend_Form_Element_Captcha(
        'captcha', // This is the name of the input field
        array('label' =&gt; 'Write the chars to the field',
        'captcha' =&gt; array( // Here comes the magic...
        // First the type...
        'captcha' =&gt; 'Image',
        // Length of the word...
        'wordLen' =&gt; 6,
        // Captcha timeout, 5 mins
        'timeout' =&gt; 300,
        // What font to use...
        'font' =&gt; '/path/to/font/FontName.ttf',
        // Where to put the image
        'imgDir' =&gt; '/var/www/project/public/captcha/',
        // URL to the images
        // This was bogus, here's how it should be... Sorry again :S
        'imgUrl' =&gt; 'http://project.com/captcha/',
)));
// Add the captcha element to the form...
$form-&gt;setAction('/index/captcha/')
        -&gt;setMethod('post')
        // Add the captcha to the form...
        -&gt;addElement($captcha)
        -&gt;addElement('submit','Submit')
// Pass the form to the view...
$this-&gt;view-&gt;form = $form;
}
</pre>
<p>On the other side, it goes something like this:</p>
<pre name="code" class="php">
public function captchaAction()
{
  $request = $this-&gt;getRequest();
  // Get out from the $_POST array the captcha part...
  $captcha = $request-&gt;getPost('captcha');
  // Actually it's an array, so both the ID and the submitted word
  // is in it with the corresponding keys
  // So here's the ID...
  $captchaId = $captcha['id'];
  // And here's the user submitted word...
  $captchaInput = $captcha['input'];
  // We are accessing the session with the corresponding namespace
  // Try overwriting this, hah!
  $captchaSession = new Zend_Session_Namespace('Zend_Form_Captcha_'.$captchaId);
  // To access what's inside the session, we need the Iterator
  // So we get one...
  $captchaIterator = $captchaSession-&gt;getIterator();
  // And here's the correct word which is on the image...

  $captchaWord = $captchaIterator['word']
  // Now just compare them...
  if($captchaInput == $captchaWord)
  {
  // OK
  }
  else
  {
  // NOK
  }
}
</pre>
<p>Easy, ain&#8217;t it?</p>
<p>Happy hacking :)</p>
<p>Tip: Using a monospace or a serif font for the words on the image (like FreeMono.ttf found by default on Ubuntu), makes the word quite unreadable &#8212; with the FreeMono.ttf about 8 out of 10 is UNreadable &#8212; so use a sans-serif font.</p>
]]></content:encoded>
			<wfw:commentRss>http://robertbasic.com/blog/a-zend-captcha-example/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
	</channel>
</rss>

