Archive for the 'Programming' category

Playing with Zend_Navigation and routes

published on August 09, 2009.

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's back now :) I finally had the time to play around with the latest Zend Framework 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 Rob Allen for his post on Bootstrapping modules in ZF 1.8!

Zend_Tool is an awesome tool. Creating a new project is like “zf create project project_name” :) And the new bootstrapping process with the Bootstrap class is somehow much clearer to me now… Anyways, lets skip to the code.

The goal

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's where the Zend_Controller_Router_Route_Regex stuff comes in:

<?php
$route = new Zend_Controller_Router_Route_Regex(
    '(?(?=^index$|^foo$)|([a-z0-9-_.]+))',
    array(
        'controller' => 'page',
        'action' => 'view',
        'slug' => null
    ),
    array(
        1 => 'slug',
    ),
    '%s'
    );

$router->addRoute('viewPage', $route);

Basically the regex does the following: if it's index or foo don't match anything, thus calling up those controllers, in any other case match what's requested and pass it to the PageController's viewAction as the slug parameter. The fourth parameter, the ‘%s’, is needed so that ZF can rebuild the route in components like the Zend_Navigation.

Now, when the PageController, viewAction get'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's or even letting the user know what part of the website is working on his request. He just request's http://example.com/some_random_article and kaboom! he get's the content :)

Page navigation

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 several blog posts which go in details about Zend_Navigation, so I won'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's where action helpers kick in. I made an action helper which makes up the structure of the links/pages. Something like this:

<?php
class Zend_Controller_Action_Helper_LinkStructure extends
        Zend_Controller_Action_Helper_Abstract{
function direct(){
$structure = array(
    array(
         'label'=>'Home page',
         'uri'=>'/'
    ),
    array(
         'label'=>'Articles',
         'uri'=>'',
         'pages'=>array(array(
                                  'label'=>'Article 1',
                                  'uri'=>'article_1'),
                              array(
                                  'label'=>'Article 2',
                                  'uri'=>'article_2'),
                         )
    )
);
return new Zend_Navigation($structure);
}
}

This is a simple example of the structure; I'm actually making it out from the database, with all the categories, subcategories and pages.

Links everywhere

To have this menu on all pages, we need to render it in the layout.phtml. Rendering is quite simple:

<?php
// somewhere in layout.phtml
<?php echo $this->navigation()->menu(); ?>

Of course, we need to pass the menu to the navigation helper somehow. To avoid doing $this->navigation($this->_helper->linkStructure()); in all the controllers, we could do that once in the bootstrap (any other ways to make it happen?):

<?php
// in Bootstrap.php somewhere in the Bootstrap class
function _initView(){

        $view = new Zend_View();
        $view->doctype('XHTML1_STRICT');
        $view->headMeta()->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->navigation($linkStructure->direct());

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

        return $view;
}

There. Now we have our menu rendered on all pages. Sexy isn't it? :)

That's it for now. Hope someone will find this useful :) Now I gotta go, need to get ready for a punk rock concert tonight!

Happy hacking!

Wordpress as CMS tutorial

published on March 14, 2009.

Wordpress is one of the best blogging platforms out there — if not the best. It's very powerful, can be easily extended and modified. It's documentation is very well written and, so far, had answer to all of my crazy questions :)

You know what'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 Roger, I thought of one way how could Wordpress be transformed into a CMS. Note the “one way”. This is not the only way for doing this, and, most likely, not the best way.

I didn't look much, but I think that there are some nice plugins out there that can do this. But, where's the fun in the download, upload, activate process? Nowhere!

I will show you how to change your Wordpress into a CMS and it really doesn't take much coding to achieve this! The example presented here is simple and will have a static page for it's home page, another static page for the “Portfolio” 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 ;)

Static pages

Things you should know: each static page has it's title, it's slug or name (the thing that shows up in your browsers address bar: http://example.com/portfolio/ - right there, the portfolio is the slug!), has the parent attribute and the template attribute. The parent attribute is used when it'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 static pages and how to create your own page templates.

If you want to, you can download the theme I created for this tutorial from here (it's not a designers masterpiece, what did you expect?), or you can use any theme you want.

I hope you read the part on creating page templates, I really don't feel like explaining the next part.

Create 3 new files in your template directory (if you're using my theme, these files are already there): home.php, portfolio.php and blog.php. Contents of these files are:

// home.php
<?php
/*
Template Name: Home
*/
?>

// portfolio.php
<?php
/*
Template Name: Portfolio
*/
?>

// blog.php
<?php
/*
Template Name: Blog
*/

// Which page of the blog are we on?
$paged = get_query_var('paged');
query_posts('cat=-0&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');
?>

To understand the contents of the blog.php file, please take a look at this.

Now, go to the dashboard, the Pages section and write 3 new static pages:

  • Home, with the slug home, for the template choose Home from the drop-down list (it's on the right side) and the parent leave as is (Main Page)
  • Portfolio, with the slug portfolio, for the template choose Portfolio
  • Blog, with the slug blog, for the template choose Blog

You can add some content to the Home and Portfolio pages, but don't add any to the Blog page.

Organizing links

Now, let'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!

Go to Settings->Reading and where it says “First page displays” choose “A static page”, and under the “Front page” drop-down choose “Home”.

Now, go to Settings->Permalinks and change the “Custom structure” to /blog/%postname%/ or whatever is your preferred permalinks structure, but it must start with /blog/! If Wordpress can't write to your .htaccess file (I hope it can't!), open it up in your editor and type the following (or similar, depends on your setup):

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

The point is in the RewriteBase, with that we'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're done with organizing the links.

While you'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).

Time for coding!

Here are two functions I wrote for retrieving content from static pages which will be then included in other static pages:

// functions.php
<?php

/**
* Gets last $number_of_subpages from their $parent_page
* If the <!--more--> 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 <!--more--> 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->get_results("SELECT * FROM $wpdb->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=>$subpage)
            if(strpos($subpage->post_content, '<!--more-->') !== false)
            {
                $short_content = explode('<!--more-->', $subpage->post_content, 2);
                $subpages[$key]->post_content = $short_content[0] . '<a href="' . get_permalink($subpage->ID) . '">Read more...</a>';
            }
        }
    }

    return $subpages;
}

function wpascms_get_parent_page_ID($parent_page)
{
    global $wpdb;

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

    return $id;
}

?>

The first function, wpascms_get_subpages() returns the given number of subpages from a specific parent page. By default it will break the content on the tag and append a “Read more…” 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'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's slug. To read more on querying the database, read this page.

Here's how I'm calling this function on my example Home page:

<?php
/*
Template name: Home
*/

get_header();
?>

    <div id="home">
    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

        <h2><?php the_title(); ?></h2>

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

    <?php endwhile; endif; ?>
    </div><!-- home -->

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

<?php
get_footer();
?>

In words: including the header, then showing any content of the home page. After that getting the subpages: by default, wpascms_get_subpages() is getting the newest 2 subpages of the portfolio page. I'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.

Here's another example from the portfolio page:

<?php
/*
Template name: Portfolio
*/

get_header();
?>

    <div id="portfolio">
    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

        <h2><?php the_title(); ?></h2>

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

    <?php endwhile; endif; ?>
    </div><!-- home -->

    <div id="latest_works">

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

<?php
get_footer();
?>

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.

All subpages can be viewed each on it's own page, but that is just a plain ol’ page.php file, so I'll skip that.

Don't limit yourself to the existing plugins or waiting for one tutorial/example that will show how you can make everything. Don't be afraid to get your hands dirty by hacking some code. It really doesn't take too much to create magic with Wordpress ;)

Cheers!

Online resources for Zend Framework

published on March 03, 2009.

Besides the official documentation and the Quickstart, there are many useful resources for Zend Framework, like blogs and Twitter. I did my best to collect them. If you know something that's not listed here, but should be, please leave a comment and I'll update the post :)

Update #1 (seconds after publishing): Gotta love Twitter. Already got a message that I missed a blog. List is updated.

Update #2: Added more blogs to the list, thanks Jani for the recommendations!

Update #3: Thanks to Federico and Pablo, even more stuff to add :)

Update #4: Thank you Jon and Cal :)

Update #5: This is growing up into a pretty big list :) new stuff added!

Update #6: Should I keep adding these Update #x lines? :)

Update #7: A bunch of new stuff!

Update #8: A new ZF application via Federico's blog!

Blogs

Blogs are probably the most important resources out there. Besides the posts, comments can add a great value to the topic, so be sure to read them too. Here are the blogs that have posts on ZF and were updated recently (in the past month or two):

Also, I recommend subscribing to PHPDeveloper's and Zend Developer Zone's feeds, just in case I missed some good blogs ;)

Twitter

On Twitter there are many friendly developers willing to help out with any problems related to Zend Framework &#151 just write your question with a ZF hashtag and someone will most likely show up with the answer :)

Books

These two books are a must read. That is all :)

Surviving The Deep End — a free online book that is written chapter by chapter. Author is Pádraic Brady:

The book was written to guide readers through the metaphorical "Deep End". It's the place you find yourself in when you complete a few tutorials and scan through the Reference Guide, where you are buried in knowledge up to your neck but without a clue about how to bind it all together effectively into an application. This take on the Zend Framework offers a survival guide, boosting your understanding of the framework and how it all fits together by following the development of a single application from start to finish. I'll even throw in a few bad jokes for free.

Zend Framework in Action — OK, this book is not an online resource, but it is great and surely must be mentioned :) Authors are Rob Allen, Nick Lo and Steven Brown:

Zend Framework in Action is a book that covers all you need to know to get started with the Zend Framework.
The first part of the book works through the creation of web site using the MVC components (Zend_Controller, Zend_View and Zend_Db). The book then follows on by looking at user authentication and access control, forms, searching and email to round out the application. After considering deployment issues, we then look at other components that add value to a web site; including web services, PDF creation, internationalisation and caching.

Guide to Programming with Zend Framework — another great book, a must have. Written by Cal Evans.

This book covers much of the primary functionality offered by the Zend Framework, and works well both as a thorough introduction to its use and as a reference for higher-level tasks

Beginning Zend Framework — written by Armando Padilla

Beginning Zend Framework is a beginner’s guide to learning and using the Zend Framework. It covers everything from the installation to the various features of the framework to get the reader up and running quickly.

Easy PHP Websites with Zend Framework by Jason Gilmore

Easy PHP Websites with the Zend Framework is the ultimate guide to building powerful PHP websites. Combining over 330 pages of instruction with almost 5 hours of online video and all of the example code, you'll have everything you need to learn PHP faster and more effectively than you ever imagined.

Applications powered by ZF

Wanna see what's ZF capable of?

Other resources

Of course, there's the good ol’ IRC, channels are #zftalk and #zftalk.dev. For more information, visit ZFTalk.

Jani Hartikainen's Packageizer is a great tool to get only those ZF components you need.

Scienta ZF Debug Bar an awesome plugin for Zend Framework which “injects into every request a snippet of HTML with commonly used debug information.”

There's also the Zend Framework Forum. For those of you who understand it, here's a German forum www.zfforum.de.

The Zend Framework Wiki and the Zend Framework Issue Tracker are also very helpful, so, be sure to check them out.

The unofficial PEAR channel for the Zend Framework can be found at http://zend.googlecode.com/</a>.

That's all from me. This are the resources I found useful and hopefully are and will be useful for you too :)

Do you know anything I missed? If so, please, leave a comment and I'll update the post :)

Cheers!

pywst - setting up web projects quickly

published on February 22, 2009.

I wrote a Python script for automating the steps required to setup a web project environment on my local dev machine that runs on Ubuntu. Called it pywst: Python, Web, Svn, Trac. That's the best I could do, sorry :P

The main steps for setting up a new project are:

  • Create a virtual host
  • Add it to /etc/hosts
  • Enable the virtual host
  • Import the new project to the SVN repository
  • Checkout the project to /var/www
  • Create a TRAC environment for the project
  • Restart Apache

After these steps I have http://projectName.lh/ which points to /var/www/projectName/public/, SVN repo under http://localhost/repos/projectName/ and the TRAC environment under http://localhost/trac/projectName/.

As I have this ability to forget things, I always forget a step or 2 of this process. Thus, I wrote pywst (note, this is a txt file, to use it, save it to your HDD and rename it to pywst.py). It's not the best and nicest Python script ever wrote, but gets the job done. All that is need to be done to setup a project with pywst is:

sudo ./pywst.py projectName

2 things are required: to run it with sudo powers and to provide a name for the project.

Future improvements

The first, and the most important is to finish the rollback() method. Now, it only exits pywst when an error occurs, but it should undo all the steps made prior to the error.

Second, to make it work on other distros, not only on Ubuntu. That would require for me getting those other distros, set them up, look where they store Apache and stuff, where's the default document root, etc. Hmm… This will take a while :)

Third, support PHP frameworks - Zend Framework, CodeIgniter and CakePHP — ZF is a must :P Under support I mean to create the basic file structure for them automagically.

Cheers!

Login example with Zend_Auth

published on January 05, 2009.

Happy New Year! Hope everyone had a blast for New Year's Eve and managed to get some rest :) This is my first working day for this year. I'm still kinda lazy and sleepy. And I wanna eat something all the time. Damn you candies!!!

So, here's what I'm going to do: authenticate an user against a database table using Zend Framework's Zend_Auth component. It's really a piece of cake. You can see a working example here: http://robertbasic.com/dev/login/</a>. Feel free to test it and report any misbehavior down in the comments. 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.

Preparation

Because I'm gonna use a database, be sure to have set the default database adapter in the bootstrap file, I have it setup like this:

<?php
$config = new Zend_Config_Ini('../application/dev/config/db_config.ini', 'offline');
$registry = Zend_Registry::getInstance();
$registry->set('db_config',$config);
$db_config = Zend_Registry::get('db_config');
$db = Zend_Db::factory($db_config->db);
Zend_Db_Table::setDefaultAdapter($db);

I'll need it later in the code. The table structure is as follows:

--
-- 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 ;

The login controller

The magic happens in the LoginController. It has two actions: indexAction and logoutAction. The indexAction will take care of showing the login form and processing the login process. The logoutAction will just logout the user. You would never figure out that one on your own, right?

Now, let's get to the fun part — the code:

<?php
class Dev_LoginController extends Zend_Controller_Action
{
    public function indexAction()
    {
        // If we're already logged in, just redirect
        if(Zend_Auth::getInstance()->hasIdentity())
        {
            $this->_redirect('dev/secured/index');
        }

        $request = $this->getRequest();
        $loginForm = $this->getLoginForm();

        $errorMessage = "";

Not much happening here: if the user is already logged in, I don't want him at the login form, so just redirect him somewhere else; most likely to a home page or a control panel's index page.

The Zend_Auth implements the Singleton pattern — if you're not familiar with it read http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction</a> and http://www.php.net/manual/en/language.oop5.patterns.php</a> (at php.net scroll down to the example #2).

So, I'm just asking the Zend_Auth does it have an user identity stored in it; the identity gets stored only upon successful log in. I'm also getting the request object. The getLoginForm() is a function that I wrote for assembling the login form and is a part of the LoginController, I'll show it's code later.

<?php
if($request->isPost())
{
    if($loginForm->isValid($request->getPost()))
    {
        // get the username and password from the form
        $username = $loginForm->getValue('username');
        $password = $loginForm->getValue('password');

This doesn't needs a lot of explanation: if it's a post request, it means the form is submitted. If the submitted data is valid, just get the wanted values from the form.

<?php
        $dbAdapter = Zend_Db_Table::getDefaultAdapter();
        $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);

        $authAdapter->setTableName('zendLogin')
                    ->setIdentityColumn('username')
                    ->setCredentialColumn('password')
                    ->setCredentialTreatment('MD5(?)');

Here I'm getting the default database adapter, so I know whit which database I'm working with. Then I'm creating an adapter for Zend_Auth, which is used for authentication; the docs give good explanation on the adapter, read it here: http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction.adapters</a>.

Next, I'm telling the authentication adapter which table to use from the database, and which columns from that table. Also, I'm telling it how to treat the credentials — the passwords are stored as MD5 hashes, so the submitted passwords will first be MD5ed and then checked.

<?php
        // pass to the adapter the submitted username and password
        $authAdapter->setIdentity($username)
                    ->setCredential($password);

        $auth = Zend_Auth::getInstance();
        $result = $auth->authenticate($authAdapter);

I'm passing to the adapter the user submitted username and password, and then trying to authenticate with that username and password.

<?php
        // is the user a valid one?
        if($result->isValid())
        {
            // get all info about this user from the login table
            // ommit only the password, we don't need that
            $userInfo = $authAdapter->getResultRowObject(null, 'password');

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

            $this->_redirect('dev/secured/index');
        }

If the user is successfully authenticated, get all information about him from the table (if any), like the real name, E-mail, etc. I'm leaving out the password, I don't need that. Next I'm getting the Zend_Auth's default storage and storing in it the user information. In the end I'm redirecting it where I want it.

<?php
else
{
    $errorMessage = "Wrong username or password provided. Please try again.";
}
}
}
$this->view->errorMessage = $errorMessage;
$this->view->loginForm = $loginForm;
}

And this is the end of the indexAction. I know I could take the correct message from $result with getMessages(), but I like more this kind of message, where I'm not telling the user which part did he got wrong.

<?php
public function logoutAction()
{
    // clear everything - session is cleared also!
    Zend_Auth::getInstance()->clearIdentity();
    $this->_redirect('dev/login/index');
}

This is the logoutAction. I'm clearing the identity from Zend_Auth, which is also clearing all data from the Zend_Auth session namespace. And, of course, redirecting back to the login form.

<?php
protected function getLoginForm()
{
    $username = new Zend_Form_Element_Text('username');
    $username->setLabel('Username:')
            ->setRequired(true);

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

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

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

    return $loginForm;
}

As promised, here's the code for getLoginForm function. That's the whole LoginController code, not really a rocket science :) Sorry if it's a bit hard to keep up with the code, I needed it to break it up in smaller pieces…

And here's the view script for the indexAction.

<?php
<h2>Zend_Login example</h2>

<p>
Hello! This is an example of authenticating users with the Zend Framework...
</p>

<p>Please login to proceed.</p>

<?php if($this->errorMessage != ""): ?>
<p class="error"><?= $this->errorMessage; ?></p>
<?php endif; ?>

<?= $this->loginForm; ?>

Other controllers

Couldn't come up with a better subtitle :(

Here's an example how to require the user to log in to see the page: in the init() method ask Zend_Auth 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 “whole controller”. Implement the same only to the indexAction, and the user will have to only log in to see the index page; he'll be able to access another page without logging in.

<?php
class Dev_SecuredController extends Zend_Controller_Action
{
    function init()
    {
        // if not logged in, redirect to login form
        if(!Zend_Auth::getInstance()->hasIdentity())
        {
            $this->_redirect('dev/login/index');
        }
    }

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

        $this->view->username = $userInfo->username;
        $this->view->name = $userInfo->name;
        $this->view->email = $userInfo->email;
    }

    public function anotherAction()
    {
    }
}

I'm also reading out the user information from the Zend_Auth's storage, that I have stored there during the log in process.

So there. A fully working login system, which can be setup in a really short time.

Update: If you want, you can get an example source code from here: zendLogin.zip ~8kB

Happy hacking!

Robert Basic

Robert Basic

Software developer making web applications better.

Let's work together!

I would like to help you make your web application better.

Robert Basic © 2008 — 2020
Get the feed