15

Zend Framework sign up and authentication

After writing separate articles on different Zend framework topics, its now time to write a full fledge tutorials. I am starting from a simple sign up and login authentication example and hopefully will discuss some advance topic in future.

So lets get started.

First create a table in your database by executing the following sql query.

CREATE TABLE ‘users’ (

      ‘id’ int(11) NOT NULL auto_increment,

      ‘firstname’ varchar(100) default NULL,

      ‘lastname’ varchar(100) default NULL,

      ‘email’ varchar(255) NOT NULL,

      ‘username’ varchar(100) NOT NULL,

      ‘password’ varchar(15) NULL,

      PRIMARY KEY  (’id’)

    )

Next create a model against this table in your application/model/ directory. I am creating Users.php and writing the following code in it.

class Users extends Zend_Db_Table
 {
      protected $_name=”users”;
 }
?>

Now create a controller named AuthController.php in application/controllers/ directory and place the following code in it

class AuthController extends Zend_Controller_Action
{
    public function loginAction()
    {
    }
    public function signupAction()
    {
    }
    public function logoutAction()
    {
    }
    public function homeAction()
    {
    }
}

As we have now create our controller and three actions, we will need to create templates files for actions. Go application/views/scripts and create a folder named “auth” and create three files in application/views/scripts/auth named

    login.phtml

    signup.phtml

    logout.phtml

    home.phtml

As we will need to have forms for sign up and login so we are going to create to files named “LoginForm.php” and “RegistrationForm.php” for these forms in application/forms/ directory.

In LoginForm.php place the following code

class LoginForm extends Zend_Form
{
    public function init()
    {
    }
}
class LoginForm extends Zend_Form
{
    public function init()
    {
    }
}

and in the RegistrationForm.php place the following code

class RegistrationForm extends Zend_Form
{
    public function init()
    {
    }
}

So far you can see that we have created all our necessary files.

No lets put the application logic in these files.

We are starting from the forms first.

In LoginForm.php, write the following code

class LoginForm extends Zend_Form
{
    public function init()
    {
        $username = $this->createElement(’text’,'username’);
        $username->setLabel(’Username: *’)
                ->setRequired(true);

        $password = $this->createElement(’password’,'password’);
        $password->setLabel(’Password: *’)
                ->setRequired(true);

        $signin = $this->createElement(’submit’,’signin’);
        $signin->setLabel(’Sign in’)
                ->setIgnore(true);

        $this->addElements(array(
                        $username,
                        $password,
                        $signin,
        ));
    }
}

In the above form we are creating two text elements named “usernam” and “password”, set their labels and setRequred to true. Next we create a submit button.
Similarly in RegistrationForm.php, write the following code

class RegistrationForm extends Zend_Form
{
    public function init()
    {
        $firstname = $this->createElement('text','firstname');
        $firstname->setLabel('First Name:')
                    ->setRequired(false);

        $lastname = $this->createElement('text','lastname');
        $lastname->setLabel('Last Name:')
                    ->setRequired(false);

        $email = $this->createElement('text','email');
        $email->setLabel('Email: *')
                ->setRequired(false);

        $username = $this->createElement('text','username');
        $username->setLabel('Username: *')
                ->setRequired(true);

        $password = $this->createElement('password','password');
        $password->setLabel('Password: *')
                ->setRequired(true);

        $confirmPassword = $this->createElement('password','confirmPassword');
        $confirmPassword->setLabel('Confirm Password: *')
                ->setRequired(true);

        $register = $this->createElement('submit','register');
        $register->setLabel('Sign up')
                ->setIgnore(true);

        $this->addElements(array(
                        $firstname,
                        $lastname,
                        $email,
                        $username,
                        $password,
                        $confirmPassword,
                        $register
        ));
    }
}

In the above code we have created several elements and place them in the form. Keep in mind that we have place * next to compulsory elements labels.
As we have now created our forms, next step is to display these in the templates files. However to do this we will first need to initialize these in our controller
So in AuthController.php, write the following code

class AuthController extends Zend_Controller_Action
{
    public function homeAction()
    {
        $storage = new Zend_Auth_Storage_Session();
        $data = $storage->read();
        if(!$data){
            $this->_redirect('auth/login');
        }
        $this->view->username = $data->username;
    }

    public function loginAction()
    {
        $users = new Users();
        $form = new LoginForm();
        $this->view->form = $form;
        if($this->getRequest()->isPost()){
            if($form->isValid($_POST)){
                $data = $form->getValues();
                $auth = Zend_Auth::getInstance();
                $authAdapter = new Zend_Auth_Adapter_DbTable($users->getAdapter(),'users');
                $authAdapter->setIdentityColumn('username')
                            ->setCredentialColumn('password');
                $authAdapter->setIdentity($data['username'])
                            ->setCredential($data['password']);
                $result = $auth->authenticate($authAdapter);
                if($result->isValid()){
                    $storage = new Zend_Auth_Storage_Session();
                    $storage->write($authAdapter->getResultRowObject());
                    $this->_redirect('auth/home');
                } else {
                    $this->view->errorMessage = "Invalid username or password. Please try again.";
                }
            }
        }
    }
    public function signupAction()
    {
        $users = new Users();
        $form = new RegistrationForm();
        $this->view->form=$form;
        if($this->getRequest()->isPost()){
            if($form->isValid($_POST)){
                $data = $form->getValues();
                if($data['password'] != $data['confirmPassword']){
                    $this->view->errorMessage = "Password and confirm password don't match.";
                    return;
                }
                if($users->checkUnique($data['username'])){
                    $this->view->errorMessage = "Name already taken. Please choose      another one.";
                    return;
                }
                unset($data['confirmPassword']);
                $users->insert($data);
                $this->_redirect('auth/login');
            }
        }
    }

    public function logoutAction()
    {
        $storage = new Zend_Auth_Storage_Session();
        $storage->clear();
        $this->_redirect('auth/login');
    }
}

It will be hard for beginners to understand the above code. So lets break it and see what this code is all about.

public function homeAction()
    {
        $storage = new Zend_Auth_Storage_Session();
        $data = $storage->read();
        if(!$data){
            $this->_redirect('auth/login');
        }
        $this->view->username = $data->username;
    }

The above code is very simple. We first create instance of Zend_Auth_Storage_Session class. Next we call its read method. This will return a row of records if the users is authenticated, otherwise null.
We check if the data is null. If yes, we redirect our page to the login action.
If data is found, it means that user is authenticated and we assign username to the view template. So display welcome message in our home.phtml template, open views/scripts/auth/home.phtml and write the following code.

Welcome <?=$this->username?>,<br>

    This is your home page<br>

    <a href=”<?=$this->url(array(’controller’=>’auth’,'action’=>’logout’))?>”>click here to logout</a>

In the code above we have a link to the logout action, which simply destroy our session.
Next

public function loginAction()
    {
        $users = new Users();
        $form = new LoginForm();
        $this->view->form = $form;
        if($this->getRequest()->isPost()){
            if($form->isValid($_POST)){
                $data = $form->getValues();
                $auth = Zend_Auth::getInstance();
                $authAdapter = new Zend_Auth_Adapter_DbTable($users->getAdapter(),'users');
                $authAdapter->setIdentityColumn('username')
                            ->setCredentialColumn('password');
                $authAdapter->setIdentity($data['username'])
                            ->setCredential($data['password']);
                $result = $auth->authenticate($authAdapter);
                if($result->isValid()){
                    $storage = new Zend_Auth_Storage_Session();
                    $storage->write($authAdapter->getResultRowObject());
                    $this->_redirect('auth/home');
                } else {
                    $this->view->errorMessage = "Invalid username or password. Please try again.";
                }
            }
        }
    }

In the fist two lines we create instances of our model and login form with statements

$users = new Users();
$form = new LoginForm();

In the third line we assign form instance to view template for display purpose.
The logic of logging in is defined in the next lines
We first check that the users has posted the request. If yes we check that he has submitted valid form. If both the condition return true, we get the values submitted as

$data = $form->getValues();

Next we create instance of Zend_Auth with code

$auth = Zend_Auth::getInstance();

and $authAdapter with

$authAdapter = new Zend_Auth_Adapter_DbTable($users->getAdapter(),’users’);

To perform authentication we will need to either use existing Adapters provided by Zend or create our own.

Here I am using DbTable Adapter provided by Zend, giving adapter and database table name. our table name is users.
Next we set identity and credential columns.
After that we give posted values to the $adapter.
To perform authentication we will need to call Zend_Auth authenticate() method, for this we write

$result = $auth->authenticate($authAdapter);

Next we check if the result is valid with statement $result->isValid(). This either return true or false. If it return true it means that we found a record in the database.
If valid record is found we create session instance and store the user data in the session with statements

$storage = new Zend_Auth_Storage_Session();
$storage->write($authAdapter->getResultRowObject());

and redirect our request to home action.

$this->_redirect(’auth/home’);

If result is not valid we assign error message to our template file
In application/views/scripts/login.phml, write the following

<?

    if(isset($this->errorMessage)){

                echo $this->errorMessage;

    }?>

    <?

                echo $this->form;

    ?>

    <a href=”<?=$this->url(array(’controller’=>’auth’,'action’=>’signup’))?>”>New users click here?</a>

In the code above we first check the error message, if set we display it.
In the next line we display our login form.
Next

public function signupAction()
    {
        $users = new Users();
        $form = new RegistrationForm();
        $this->view->form=$form;
        if($this->getRequest()->isPost()){
            if($form->isValid($_POST)){
                $data = $form->getValues();
                if($data['password'] != $data['confirmPassword']){
                    $this->view->errorMessage = "Password and confirm password don't match.";
                    return;
                }
                if($users->checkUnique($data['username'])){
                    $this->view->errorMessage = "Name already taken. Please choose      another one.";
                    return;
                }
                unset($data['confirmPassword']);
                $users->insert($data);
                $this->_redirect('auth/login');
            }
        }
    }

This action is used for signup purpose. We create instance of our model class and Registration Form. And assign form to our view template.
Check for the post request and valid form.
If the form is valid we get form values. Check if both the password fields don’t have same data. If they are not same we assign error message to the view template.
Next we call our checkUnique() method of the model class. This checkUnique() method check the data in the database. If row with the posted username is already in the database it return ture, means username already exist in the database. If username found we assign error message to view telling the user to choose another username. It not we insert the data in the database. And redirect the request to login action.
Our model class look as

class Users extends Zend_Db_Table
{
    protected $_name="users";
    function checkUnique($username)
    {
        $select = $this->_db->select()
                            ->from($this->_name,array('username'))
                            ->where('username=?',$username);
        $result = $this->getAdapter()->fetchOne($select);
        if($result){
            return true;
        }
        return false;
    }
}

To create a template file for the signup action, place the following code in views/scripts/auth/signup.phtml

<?
if(isset($this->errorMessage)){

            echo $this->errorMessage;

}?>

<h4>Sign up</h4>

<?

echo $this->form;

?>

first we check for the error, if error message is set in the action we display that.
Next we display our Registarion form.
The last and final thing is our logout action.

public function logoutAction()
    {
        $storage = new Zend_Auth_Storage_Session();
        $storage->clear();
        $this->_redirect('auth/login');
    }

Here we create instance of Zend_Auth_Storage_Session and clear it.
And we then redirect our request to login action.

Filed in: Tutorial Tags: 

15 Responses to "Zend Framework sign up and authentication"

  1. hex says:

    Hello, thanks for the tutorial, but I get a Fatal error: Class ‘Users’ not found in /var/www/app/application/controllers/AuthController.php on line 16. What must i do? Thanks.

  2. Faheem Abbas says:

    Well hex.
    It seems that you haven't include path to your models in your bootstrap file.
    you need to write,
    set_include_path('path/to/models'.get_include_path());

    I usually do it like

    set_include_path('.'
    . PATH_SEPARATOR . ROOT_DIR . '/application'
    . PATH_SEPARATOR . ROOT_DIR . '/application/models'
    . PATH_SEPARATOR . get_include_path()
    );

  3. hex says:

    thanks, you were right, i wasn't using the autoloader right. But now, when i try to click, new user, register here link i get… Fatal error: Call to a member function getAdapter() on a non-object

  4. Faheem Abbas says:

    It seems that you haven't configured your database correctly in your bootstrap file.

  5. zeljko says:

    did you ever make this thing work?

  6. Anonymous says:

    i just cant get this to work

    always get

    Warning: include(LoginForm.php) [function.include]: failed to open stream: No such file or directory in C:\Archivos de programa\Zend\ZendServer\share\ZendFramework\library\Zend\Loader.php on line 83

    Warning: include() [function.include]: Failed opening 'LoginForm.php' for inclusion (include_path='C:\Archivos de programa\Zend\Apache2\htdocs\integra2;.;C:\Archivos de programa\Zend\ZendServer\share\ZendFramework\library') in C:\Archivos de programa\Zend\ZendServer\share\ZendFramework\library\Zend\Loader.php on line 83

    Fatal error: Class 'LoginForm' not found in C:\Archivos de programa\Zend\Apache2\htdocs\integra2\application\default\controllers\AuthController.php on line 28

  7. Anonymous says:

    FIXED:

    with

    set_include_path(INTEGRA_PATH_ROOT. "\\application\\default\\models" . PATH_SEPARATOR . INTEGRA_PATH_ROOT. "\\application\\forms" . PATH_SEPARATOR . INTEGRA_PATH_ROOT . PATH_SEPARATOR . get_include_path());

    this instruction fix the LoginForm and Users "not found " problem, hope itll help someone

  8. Anonymous says:

    Hi,, thanks for this tutorial it really works so cool and able to learn many things

  9. Erdal YAZICIOGLU says:

    Thank you so much for the very clear and explainatory tutorial.. Great job

  10. Anonymous says:

    In stead of all set_include_paths, you can also let your model class start with Default_Model_, so in this case Default_Model_Users. Then it will be automatically included

  11. santhosh j says:

    hi this is my index.php file
    error_reporting(E_ALL|E_STRICT);

    date_default_timezone_set('Europe/London');

    set_include_path('.' . PATH_SEPARATOR . './library/'

    . PATH_SEPARATOR . './application/models/'

    . PATH_SEPARATOR . './application/lib/'

    . PATH_SEPARATOR . get_include_path());

    include "Zend/Loader.php";

    Zend_Loader::loadClass('Zend_Controller_Front');

    Zend_Loader::loadClass('Zend_Registry');

    Zend_Loader::loadClass('Zend_View');

    Zend_Loader::loadClass('Zend_Config_Ini');

    Zend_Loader::loadClass('Zend_Db');

    Zend_Loader::loadClass('Zend_Db_Table');

    Zend_Loader::loadClass('Zend_Debug');

    Zend_Loader::loadClass('Zend_Auth');

    // load configuration

    $config = new Zend_Config_Ini('./application/config.ini', 'general');

    Zend_Registry::set('config', $config);

    // setup database

    $db = Zend_Db::factory($config->db->adapter,

    $config->db->config->toArray());

    Zend_Db_Table::setDefaultAdapter($db);

    Zend_Registry::set('db', $db);

    // setup controller

    $frontController = Zend_Controller_Front::getInstance();

    $frontController->throwExceptions(true);

    $frontController->setControllerDirectory('./application/controllers');

    // run!

    $frontController->dispatch();

    but its throwing error like
    The requested URL /zendauth/auth/login was not found on this server. Apache/2.2.11 (Ubuntu) PHP/5.2.6-3ubuntu4.2 with Suhosin-Patch Server at localhost Port 80

    what is the problem please help me out thank you…have a nice day

  12. Anonymous says:

    Thanks for this great post. I'm not understanding where in this code you put your database configuration (mysql: username, password, dbname, table name)

  13. santhosh j says:

    hi thanks for ur reply i have my db in the config.ini

  14. Anonymous says:

    Hello sir,do this function important in sign up and login authentification form : public function preDispatch()

  15. bhargav says:

    hell sir i need 2 know what code i have to write in bootstrap.php and index.php pls help me give me a small example… thank u

Leave a Reply

Submit Comment

© 9358 Faheem Abbas. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
Top Footer