Sistema de Login

Por zsamer en Mayo 1, 2008

Mi objetivo en este articulo es simplemente mostrar una forma de implementar un sistema de login de usuarios con Zend Framework.

Antes de empezar a tirar lineas de código necesitamos tener claro que componentes de ZF vamos a utilizar, por supuesto que el más importante es Zend_Auth, el cual provee un API de autenticación que incluye diferentes adaptadores para diferentes escenarios, en nuestro caso vamos a utilizar uno que nos permita chequear contra la base de datos Zend_Auth_Adapter_DbTable, requiere una instancia de nuestro objeto de conexión a la base de datos (Zend_Db_Adapter_Abstract) que es pasado por el constructor.

El adaptador mencionado arriba tiene la habilidad de autenticarse contra las credenciales almacenada en la base de datos, para el ejemplo vamos a trabajar como siempre con nuestro querido motor Mysql. Aquí tenemos tres parámetros muy importantes que necesitamos configurar y estos son:

  1. tableName el nombre de la tabla que contiene las credenciales.
  2. identityColumn que corresponde al campo de nuestra tabla que representa la identidad que debe contener valores único como el nombre de usuario o email.
  3. credentialColumn correspondiente a la credencial del usuario, comúnmente un password, ojalas encriptado.

Para comenzar con nuestro ejemplo ideal sería haber leído algo del set de artículos Comenzando con ZendFramwork, lo que vamos a hacer es retomar lo que ya habíamos hecho y adaptarlo a un sistema de usuarios donde sólo los usuarios logeados/autenticados podrán hacer comentarios, suena interesante ¿no?, bueno si aun están interesados en seguir leyendo esta entrada desde ya les doy la bienvenida.

Nuestra estructura de directorio sería exactamente la misma, ahí no cambia nada, solo necesitaremos agregar el Controlador, Modelo y vista en función del usuario y hacer un par de modificaciones a lo que ya teníamos del sistema de Comentarios.

Lo primero es agregar una sola linea en nuestro archivo index.php o puerta de entrada al sistema aveces llamado bootstrap file.

Aquí sólo vamos a agregar la autocarga de clases que trae Zend Framwork, Zend_Loader::registerAutoload() nos incluye las clases sin tener que cargarlas explicitamente con Zend_Loader::loadClass(), includes o require cuando las necesitemos, ZF lo hace automáticamente por nosotros :-) .

Entonces nuestro index.php o bootstrap quedaría de la siguiente forma:

quickstart/public/index.php

PHP:
  1. <?php
  2. /** Bootstrap */
  3. /** Configuración de manejo de error */
  4. error_reporting(E_ALL | E_STRICT);
  5. ini_set('display_startup_errors', 1);
  6. ini_set('display_errors', 1);
  7.  
  8. /** Configuración de Directorios */
  9. $rootPath = dirname(dirname(__FILE__));
  10. set_include_path(get_include_path() . PATH_SEPARATOR .
  11.                  $rootPath . '/application/config' . PATH_SEPARATOR .
  12.                  $rootPath . '/application/models' . PATH_SEPARATOR .
  13.                  $rootPath . '/library' . PATH_SEPARATOR .
  14.                  $rootPath . '/public');
  15.  
  16. /** Nuevo Autocarga de clases de Zend FrameWork */        
  17. require_once 'Zend/Loader.php';
  18. Zend_Loader::registerAutoload();
  19.  
  20. /** Carga el archivo de configuración ini */
  21. require_once 'Zend/Config/Ini.php';
  22. $config = new Zend_Config_Ini('quickstart.ini', 'default');
  23.  
  24. /** Inicializa y conecta Base de Datos */
  25. require_once 'Zend/Db.php';
  26. require_once 'Zend/Db/Table/Abstract.php';
  27. $db = Zend_Db::factory($config->database);
  28. Zend_Db_Table_Abstract::setDefaultAdapter($db);
  29.  
  30. /** Inicializa layout */
  31. $options = array(
  32.     'layout'     => 'Main',
  33.     'layoutPath' => '../application/layouts/scripts/'
  34. );
  35.  
  36. require_once 'Zend/Layout.php';
  37. //Zend_Layout::startMvc($config->appearance);
  38. Zend_Layout::startMvc($options);
  39.  
  40. require_once 'Zend/Controller/Front.php';
  41. $frontController = Zend_Controller_Front::getInstance();
  42.  
  43. $frontController->setControllerDirectory($rootPath . '/application/controllers')
  44.                 ->throwExceptions(true)
  45.                 ->dispatch();

Nuestro layout main.html también necesitará un par de ajustes menores:

quickstart/application/layouts/scripts/main.phtml

PHP:
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html>
  3.     <head>
  4.         <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  5.         <title>Quickstart</title>
  6.     </head>
  7.     <body>
  8.         <h1>Quick start</h1>
  9.         <p>
  10.             | <a href="<?php echo $this->baseUrl; ?>">Home</a>
  11.             | <a href="<?php echo $this->baseUrl; ?>/about">About</a>
  12.             <?php if($this->loggedIn):?>
  13.                 | <a href="<?php echo $this->baseUrl; ?>/user/">Perfil</a>
  14.             <?php else:?>
  15.                 | <a href="<?php echo $this->baseUrl; ?>/user/">Login</a>
  16.             <?php endif;?>
  17.            
  18.             <?php if($this->loggedIn):?>
  19.                 | <a href="<?php echo $this->baseUrl; ?>/user/logout">Logout (<?php echo $this->user->username;?>)</a>
  20.             <?php endif;?>     
  21.            
  22.         </p>
  23. <?php echo $this->layout()->content; ?>
  24.     </body>
  25. </html>

Como se habrán dado cuenta nuestro menú del header cambió ahora incorpora algunas secciones de usuarios, si el usuario no ha iniciado sesión entonces me deberá dar un link al login de usuarios, a la inversa, si este ha iniciado sesión entonces me debería de dar la opción de perfil y logout, si estamos de acuerdos entonces sigamos viendo que sucede.

Sin duda alguna nuestro controlador y vista de los comentarios también han tenido cambios, ya que el requerimiento actual es que sólo los usuarios con sesión/logeado podrán hacer comentarios, entonces nuestro IndexController (controlador de los comentarios) quedará de la siguiente forma:

quickstart/application/controllers/IndexController.php

PHP:
  1. <?php
  2. require_once 'Zend/Controller/Action.php';
  3. class IndexController extends Zend_Controller_Action
  4. {
  5.     public function init()
  6.     {
  7.         $this->view->baseUrl = $this->_request->getBaseUrl();
  8.     }
  9.  
  10.     public function preDispatch()
  11.     {
  12.         require_once 'UserModel.php';
  13.        
  14.         if (UserModel::isLoggedIn()) {
  15.             $this->view->loggedIn = true;
  16.             $this->view->user = UserModel::getIdentity();
  17.         }
  18.     }
  19.    
  20.     public function indexAction()
  21.     {
  22.         require_once 'CommentsTable.php';
  23.         $form = CommentsTable::getAddCommentForm();
  24.  
  25.         if ($this->getRequest()->isPost()) {
  26.             if ($form->isValid($_POST)) {
  27.                 $values = $form->getValues();
  28.                 CommentsTable::createNewComments(array('comments' => $values['comments']));
  29.                 $_POST = array();
  30.             }
  31.         }
  32.  
  33.         $this->view->form = $form;
  34.         $this->view->title = 'Comentarios';
  35.         $this->view->comments = CommentsTable::getComments();
  36.     }
  37. }

Se hace uso del método preDispatch() el cual se ejecuta siempre automáticamente antes de ejecutar la acción en cuestión, en nuestro caso, tiene la función de verificar si el usuario ha iniciado sesión, si es así entonces creará una variable de la vista que almacenará el valor boleano verdadero como logeado.

También se incorpora el método init(), permite hacer todas las inicializaciones de manera muy simple sin la necesidad de sobrescribir el constructor de la clase __construct(), en nuestro caso creamos otra variable de la vista para almacenar la base Url.

Hasta ahora todo marcha como corresponde, pero aun faltan cosas, como los cambios en la vista de los comentarios, nuestro index.phtml.

quickstart\application\views\scripts\index\index.phtml

PHP:
  1. <h3><?php echo $this->title; ?></h3>
  2. <?php if($this->loggedIn):?>
  3.     <ul>
  4.     <?php foreach ($this->comments as $comment) :?>
  5.         <li><?php echo $this->escape($comment->comments); ?></li>
  6.     <?php endforeach; ?>
  7.     </ul>
  8.     <?php echo $this->form; ?>
  9. <?php else:?>
  10.     <p>Para comentar necesita estar logeado, <a href="<?php echo $this->baseUrl;?>/user/login" title="Login">Login</a></p>
  11. <?php endif;?>

Felizmente el modelo de los comentarios (CommentsTable) no sufrió cambió alguno asique lo pueden obtener del artículo anterior Comenzando con Zend Framework: IV Parte.

Bueno hasta el momento sólo hemos expuesto los cambios sufrido a nuestro sistema de comentarios, ahora nos queda exponer lo nuevo y esto es en función del Modelo, Vista y Controlador del Usuario, aquí vamos.

Como dijimos antes nuestro ejemplo vamos a utilizar a Mysql como nuestro motor de base de datos para guardar los comentarios y usuarios.

La definición o estructura de la tabla de usuarios sería:

MySQL:
  1. DROP TABLE IF EXISTS `users`;
  2. CREATE TABLE IF NOT EXISTS `users` (
  3.   `user_id` INT(11) NOT NULL AUTO_INCREMENT,
  4.   `username` VARCHAR(40) collate latin1_general_ci NOT NULL DEFAULT '',
  5.   `user_password` VARCHAR(50) collate latin1_general_ci NOT NULL DEFAULT '',
  6.   `user_email` VARCHAR(50) collate latin1_general_ci DEFAULT NULL,
  7.   PRIMARY KEY  (`user_id`)
  8. ) ENGINE=MyISAM;
  9.  
  10. --
  11. -- Volcar la base de datos para la tabla `posters`
  12. --
  13.  
  14. INSERT INTO `users` (`user_id`, `username`, `user_password`, `user_email`) VALUES
  15. (1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 'test@test.cl');

Como ven tenemos un usuario inserto, username "admin" y password "admin", esta viene encriptada con md5.

Respecto a la definición de la tabla de comentario la podrán encontrar en artículos anteriores.

Teniendo la definición de nuestra tabla de usuarios Mysql seguiremos con el controlador de usuario, nuestro UserController.

Nuestro Controlador UserController quedaría de la siguiente forma:

quickstart/application/controllers/UserController.php

PHP:
  1. <?php
  2. require_once 'Zend/Controller/Action.php';
  3.  
  4. require_once 'UserModel.php';
  5.  
  6. class UserController extends Zend_Controller_Action
  7. {
  8.     public function init()
  9.     {
  10.         $this->view->baseUrl = $this->_request->getBaseUrl();
  11.     }
  12.    
  13.     public function preDispatch()
  14.     {
  15.         require_once 'UserModel.php';
  16.        
  17.         if (UserModel::isLoggedIn()) {
  18.             $this->view->loggedIn = true;
  19.             $this->view->user = UserModel::getIdentity();
  20.         }
  21.     }
  22.    
  23.     public function indexAction()
  24.     {
  25.         $this->_forward('login');
  26.     }
  27.    
  28. /* ...más métodos Action... */
  29.     public function loginAction()
  30.     {
  31.         require_once 'Zend/Form.php';
  32.        
  33.         $form = new Zend_Form(array(
  34.             'method'   => 'post',
  35.             'action'   => $this->view->baseUrl . '/user/login',
  36.             'elements' => array(
  37.                 'nick' => array('text', array(
  38.                     'required' => true,
  39.                     'label' => 'Usuario'
  40.                 )),
  41.                 'password' => array('password', array(
  42.                     'required' => true,
  43.                     'label' => 'Password'
  44.                 )),
  45.                 'submit' => array('submit', array(
  46.                     'label' => 'Send'
  47.                 ))
  48.             ),
  49.         ));
  50.        
  51.         if ($this->getRequest()->isPost()) {
  52.             if ($form->isValid($_POST)) {
  53.                 $values = $form->getValues();
  54.                
  55.                 Zend_Loader::loadClass('Zend_Filter_StripTags');
  56.                 $filter = new Zend_Filter_StripTags();
  57.                 $nick = trim($filter->filter($this->getRequest()->getPost('nick')));
  58.                 $password = trim($filter->filter($this->getRequest()->getPost('password')));
  59.                
  60.                 try{           
  61.                     $user = new UserModel();
  62.                     $user->setMessage('El nombre de Usuario y Password no coinciden.', UserModel::NOT_IDENTITY);
  63.                     $user->setMessage('La contraseña ingresada es incorrecta. Inténtelo de nuevo.', UserModel::INVALID_CREDENTIAL);
  64.                     $user->setMessage('Los campos de Usuario y Password no pueden dejarse en blanco.', UserModel::INVALID_LOGIN);
  65.                     $user->login($nick, $password);
  66.                     $this->_redirect();
  67.                 } catch(Exception $e){
  68.                     $responseLogin = $e->getMessage();
  69.                 }
  70.  
  71.                 $this->view->responseLogin = $responseLogin;
  72.  
  73.             }
  74.         }
  75.  
  76.         $this->view->form = $form;
  77.         $this->view->title = 'Login';
  78.  
  79.     }
  80.    
  81.     public function logoutAction()
  82.     {
  83.         $user = new UserModel();
  84.         $user->logout();
  85.         $this->_redirect();
  86.     }
  87. /* ...más métodos Action... */
  88. }

Aquí tenemos varias cositas que comentar, pero devido al tiempo y longitud del articulo les dejo de tarea investigar.

Definamos nuestra clase Modelo para el usuario UserModel, ubicada dentro de la carpeta application/models/ de nuestra aplicación:

quickstart/application/models/UserModel.php

PHP:
  1. <?php
  2. require_once 'Zend/Db/Table/Abstract.php';
  3.  
  4. class UserModel extends Zend_Db_Table_Abstract
  5. {
  6.     protected $_name    = 'users';
  7.  
  8.     protected $_primary = 'user_id';
  9.  
  10.     const NOT_IDENTITY = 'notIdentity';
  11.  
  12.     const INVALID_CREDENTIAL = 'invalidCredential';
  13.  
  14.     const INVALID_USER = 'invalidUser';
  15.  
  16.     const INVALID_LOGIN = 'invalidLogin';
  17.  
  18.     /**
  19.      * Mensaje de validaciones por defecto
  20.      *
  21.      * @var array
  22.      */
  23.     protected $_messages = array(
  24.         self::NOT_IDENTITY    => "Not existent identity. A record with the supplied identity could not be found.",
  25.         self::INVALID_CREDENTIAL => "Invalid credential. Supplied credential is invalid.",
  26.         self::INVALID_USER => "Invalid User. Supplied credential is invalid",
  27.         self::INVALID_LOGIN => "Invalid Login. Fields are empty"
  28.     );
  29.  
  30.     /**
  31.      * @param string $messageString
  32.      * @param string $messageKey    OPTIONAL
  33.      * @return UserModel
  34.      * @throws Exception
  35.      */
  36.     public function setMessage($messageString, $messageKey = null)
  37.     {
  38.         if ($messageKey === null) {
  39.             $keys = array_keys($this->_messages);
  40.             $messageKey = current($keys);
  41.         }
  42.         if (!isset($this->_messages[$messageKey])) {
  43.             throw new Exception("No message exists for key '$messageKey'");
  44.         }
  45.         $this->_messages[$messageKey] = $messageString;
  46.         return $this;
  47.     }
  48.  
  49.     /**
  50.      * @param array $messages
  51.      * @return UserModel
  52.      */
  53.     public function setMessages(array $messages)
  54.     {
  55.         foreach ($messages as $key => $message) {
  56.             $this->setMessage($message, $key);
  57.         }
  58.         return $this;
  59.     }
  60.  
  61.     public function login($nick, $password)
  62.     {
  63.         if(!empty($nick) && !empty($password))
  64.         {
  65.             Zend_Loader::loadClass('Zend_Auth_Adapter_DbTable');
  66.             $autAdapter = new Zend_Auth_Adapter_DbTable(self::getDefaultAdapter());
  67.             $autAdapter->setTableName('users');
  68.             $autAdapter->setIdentityColumn('username');
  69.             $autAdapter->setCredentialColumn('user_password');
  70.             $autAdapter->setIdentity($nick);
  71.             $autAdapter->setCredential(md5($password));
  72.  
  73.             $aut = Zend_Auth::getInstance();
  74.  
  75.             $result = $aut->authenticate($autAdapter);
  76.  
  77.             switch ($result->getCode())
  78.             {
  79.                 case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
  80.                     throw new Exception($this->_messages[self::NOT_IDENTITY]);
  81.                     break;
  82.  
  83.                 case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
  84.                     throw new Exception($this->_messages[self::INVALID_CREDENTIAL]);
  85.                     break;
  86.  
  87.                 case Zend_Auth_Result::SUCCESS:
  88.                     if ($result->isValid()) {
  89.                         $data = $autAdapter->getResultRowObject();
  90.                         $aut->getStorage()->write($data);
  91.                     } else {
  92.                         throw new Exception($this->_messages[self::INVALID_USER]);
  93.                     }
  94.                     break;
  95.  
  96.                 default:
  97.                     throw new Exception($this->_messages[self::INVALID_LOGIN]);
  98.                     break;
  99.             }
  100.  
  101.         } else {
  102.             throw new Exception($this->_messages[self::INVALID_LOGIN]);
  103.         }
  104.         return $this;
  105.     }
  106.  
  107.     public function logout()
  108.     {
  109.         Zend_Auth::getInstance()->clearIdentity();
  110.         return $this;
  111.     }
  112.    
  113.     public static function getIdentity()
  114.     {
  115.         $auth = Zend_Auth::getInstance();
  116.  
  117.         if ($auth->hasIdentity()) {
  118.             return $auth->getIdentity();
  119.         }
  120.         return null;
  121.     }
  122.    
  123.     public static function isLoggedIn()
  124.     {
  125.        
  126.         return Zend_Auth::getInstance()->hasIdentity();
  127.     }
  128. /* ...más métodos del Modelo Usuario... */
  129. }

Finalmente la definición de nuestra vista del usuario sería:
quickstart\application\views\scripts\user\login.phtml

PHP:
  1. <?php if(!$this->loggedIn):?>
  2.     <h3><?php echo $this->title;?></h3>
  3.     <?php if(isset($this->responseLogin)):?>
  4.         <p><?php echo $this->responseLogin;?></p>
  5.     <?php endif;?>
  6.     <?php echo $this->form;?>
  7. <?php else:?>
  8. <h3>Perfil</h3>
  9. <p>Bienvenido <strong><?php echo $this->user->username;?></strong></p>
  10. <?php endif;?>

Tristemente hemos terminado con nuestro tutorial, espero que haya sido de utilidad para muchos y como tarea les dejo la inquietud de hacer el registro de los usuarios.

En nuestro próximo artículo vamos a hacer un Refactoring a nuestro sistema para dejarlo modular, lo que quiero decir es que vamos a tener distintos módulos y cada uno con sus respectivos Modelos, Vistas y Controladores, para que se vallan interiorizando les dejo el siguiente link.

Hasta la próxima ;-) .

Comentarios

36 Responses to “Sistema de Login”

  1. _imc_ on Mayo 2nd, 2008 9:44 am

    Fiel a la cita de lectura :D

    Un par de preguntas/comentarios…

    1) Al utilizar Zend_Loader::registerAutoload() y cargar todas las clases no sería mejor para temas de rendimiento solo cargar las clases que vamos a utilizar, aunque tengamos que ir cargandolas una a una…

    2) En el layout main.phtml en Home habría que añadir un “/” ya que a mi me toma el $this->baseUrl “mal” y me pone como acción donde este en lugar del home

    La serie continua muy interesante, siguientes pasos… formularios, más módulos, gestión de usuarios, excepciones?¿?

    Un saludo!!!

  2. zsamer on Mayo 2nd, 2008 1:32 pm

    Hola _imc_

    Respondiendo:

    1) Zend_Loader::registerAutoload() sólo carga las clases que vas utilizando/instanciando, como ej:

    $registry = Zend_Registry::getInstance();

    Al crear la instancia de Zend_Registry, registerAutoload trabaja por detrás en forma automática y hace un include de la clase antes de instanciarla.

    2) ¿Tu app esta en el root del servidor webo en una carpeta? ¿Agregaste los métodos ini() en los controladores?
    En el link del home agrega al final “/”, después de $this->baseUrl.

    saludos,

  3. Estructura Modular de Directorios : Zend Framework: Estado del Arte on Mayo 10th, 2008 3:48 am

    [...] semana pasada escribí un articulo sobre un Sitema de Login el cual continuaba con la linea del set de artículos Comenzando con Zend Framework con el fin de [...]

  4. vanvanero on Junio 18th, 2008 12:29 pm

    zsamer tiene razon el Zend_Loader::registerAutoload() solo carga las clases que va a utilizar por que es mas bien un gestor de clases mas que un simple cargador de clases, además Zend implementa el patron Singleton, que precisamente se encrga de instanciar la clase una sola vez, igual si no estas seguro pones simplemente un clearstatcache(); que se encarga de lipiar aquellas clases y objetos puedes definirlo en un metodo con el objetivo de Encapsularlo y que sea comprensible

    public static function cargarClases(){

    clearstatcache();
    Zend_Loader::registerAutoload();

    }

  5. emerge bank on Junio 28th, 2008 12:37 pm

    Nice Site!
    http://google.com

  6. J0sh on Agosto 1st, 2008 6:58 pm

    Muchas gracias por el articulo, le he pegado un rápido vistazo y ya lo tengo en favoritos listo para, en cuanto tenga un rato, estudiarlo a fondo; he comenzado el otro día a estudiar ZF y lo que necesitaba eran ayudas como esta en castellano.

    Gracias por esta ayuda, ahora lo que necesito saber es como juntar el sistema de login con las ACL.

  7. Traducción de Zend Validate con gettext y poedit « /dev/GON on Septiembre 6th, 2008 7:54 am

    [...] Tutoriales y documentación para trabajar con Zend Form abundan, así que no voy a profundizar en ello. [...]

  8. arturo on Septiembre 7th, 2008 8:16 pm

    hola……….
    Muy buena pero yo estoy utilizando el zend framework 1.5 y quisiera que alguien me ayude a utilizar zend_auth y zend_acl pero en zf 1.5 ya que el orden es más estricto en esta versión por favor cualquier informacion es valido.
    De ante mano muchas gracias………

  9. lisandro on Septiembre 26th, 2008 7:02 pm

    Un detalle…

    Hay una doble validación para el formulario, la primera esta en el controlador

    $form->isValid($_POST)

    y la segunda en el modelo

    if(!empty($nick) && !empty($password))

    Cuando se envian los dos campos vacios no pasa de la primer validación por lo tanto el mensaje q se muestra no es el nuestro sino el de ZF. No estoy muy al tanto de cuantas validaciones hace isValid() pero estimo q NO seria necesario usarlo en este caso, por favor si me equivoco soy todo ojos :0

  10. jos on Octubre 3rd, 2008 1:39 pm

    Que tal muy buen block, estoy empezando en esto del zend segui todos los bloks que llevas hasta este donde me atore hice todo al pie de la letra pero me aparece el siguinte error y no tengo idea de que sea

    Fatal error: Class ‘Zend_Auth’ not found in /var/www/Ejemplo/application/models/UserModel.php on line 231

    espero me puedas orientar

  11. zsamer on Octubre 3rd, 2008 2:53 pm

    hola jos tienes que tener en tu index.php o bootstrap esta linea Zend_Loader::registerAutoload();

    saludos.

  12. jos on Octubre 3rd, 2008 4:51 pm

    en verdad gracias me fue de mucha utilidad

  13. jos on Octubre 6th, 2008 9:56 pm

    Que tal zsamer mira ya esta corriendo el ejemplo del login pero tengo un problema los link estan rotos no sirven o se por que cuestion ya revise metodo init() y de todos modos no me fuciona estoy un poco desesperado espero me puedas ayudar

    si le doy a about me manda a

    http://localhost/Ejemplo/public/about

    login me manda a

    http://localhost/Ejemplo/public/user

    y si le doy al otro login me manda

    http://localhost/Ejemplo/public/user/login

    de ante mano gracias

  14. jos on Octubre 7th, 2008 2:12 pm

    Que tal zsamer mira ya esta corriendo el ejemplo del login pero tengo un problema los link estan rotos no sirven o se por que cuestion ya revise metodo init() y de todos modos no me fuciona estoy un poco desesperado espero me puedas ayudar

    si le doy a about me manda a

    http://localhost/Ejemplo/public/about

    login me manda a

    http://localhost/Ejemplo/public/user

    y si le doy al otro login me manda

    http://localhost/Ejemplo/public/user/login

    de ante mano gracias

  15. zsamer on Octubre 7th, 2008 3:18 pm

    ¿te arroja un error?
    ¿que error aparece?

    Son ejemplos básicos, la idea es que los links lo definan ustedes según lo que quieras hacer.

  16. jos on Octubre 7th, 2008 3:58 pm

    me aparece:

    Not Found

    The requested URL /quickstart/public/user/login was not found on this server.

    pero no entiendo por que

  17. zsamer on Octubre 7th, 2008 4:12 pm

    Mmmm. Tu problemas es muy básico.

    ¿Instalaste el mod_rewrite en tu servidor?
    ¿te fijaste en el archivo .htaccess?

    Vas a tener que repasar los post anteriores.

    Te saltaste un paso o hiciste algo mal.

    También puedes recurrir al manual oficial de ZF o Foros.

  18. jos on Octubre 7th, 2008 4:21 pm

    ok gracias en verdad muchas gracias

  19. karla on Octubre 7th, 2008 8:44 pm

    que tal buen dia estoy empezando en esto de zend en ubuntu ya hice todo pero me sale el siguiente erro

    Fatal error: Uncaught exception ‘Zend_Session_Exception’ with message ‘Session must be started before any output has been sent to the browser; output started in /var/www/quickstart/application/models/UserModel.php/2′ in /var/www/quickstart/library/Zend/Session.php:407 Stack trace: #0 /var/www/quickstart/library/Zend/Session/Namespace.php(116): Zend_Session::start(true) #1 /var/www/quickstart/library/Zend/Auth/Storage/Session.php(87): Zend_Session_Namespace->__construct(’Zend_Auth’) #2 /var/www/quickstart/library/Zend/Auth.php(91): Zend_Auth_Storage_Session->__construct() #3 /var/www/quickstart/library/Zend/Auth.php(133): Zend_Auth->getStorage() #4 /var/www/Ejemplo/application/models/UserModel.php(231): Zend_Auth->hasIdentity() #5 /var/www/quickstart/application/controllers/UserController.php(23): UserModel::isLoggedIn() #6 /var/www/quickstart/library/Zend/Controller/Action.php(495): UserController->preDispatch() #7 /var/www/quickstart/library/Zend/Controller/Dispatcher/Standard.php(293): Zend_Controller_Action->dispatch(’loginA in /var/www/quickstart/library/Zend/Session.php on line 407

    espero me puedad ayudar se los agradeceria muchisimo

  20. zsamer on Octubre 7th, 2008 9:18 pm

    es porque tienes una salida o output antes de finalizar el proceso o aplicación.

    Revisa que no tengas ningún espacio en blanco en tus archivos php (revisarlos todos).

    No pueden haber espacios antes de "< ?php" ni tampoco después de "?>"

  21. gabnet on Octubre 10th, 2008 12:32 pm

    Me parece interesante y bien estructurada la solución del artículo. Quisiera por otra parte consultarte algo que me ha estado molestando un poco de este framework y es que a la hora de ubicar visualmente los bloques/campos de un formulario en la capa de vista, el módulo zend_form es muy eficiente generando el layout uno debajo del otro o aplicando un determinado patrón (gracias a los decoradores) pero, si quiero ubicar algunos alineados al costado y otros debajo por ejemplo, ya no es tan sencillo. No puedo simplemente ubicar a mi gusto algunas variables en la capa de vista como haría con Smarty u otro framework de vista. La alternativa de usar sub-forms u otras vueltas haciendo el código del form más complejo para lograr el efecto deseado me resulta casi tan desprolijo como usar capas de CSS para reubicar los bloques/campos (digo bloques por componerse del campo propiamente dicho, mensaje de error y label). Este detalle planteado sobre los forms me complica a la hora de delegarle a otra persona el desarrollo de plantillas o el diseño gráfico del sistema. Agradezco cualquier sugerencia que puedas aportar o consideres pertinente. Saludos.

  22. zsamer on Octubre 10th, 2008 3:39 pm

    Revisa el manual, la solución es crear tu propia clase Decorator que extienda de Zend_Form_Decorator_Abstract y ahí haces el render a tu gusto.

    Revisa esto:
    Creating Custom Form Markup Using Zend_Form_Decorator

  23. Estructura Modular de Directorios | Zend Framework: Estado del Arte on Octubre 10th, 2008 11:22 pm

    [...] semana pasada escribí un articulo sobre un Sitema de Login el cual continuaba con la linea del set de artículos Comenzando con Zend Framework con el fin de [...]

  24. MLM Leads on Octubre 15th, 2008 4:54 am

    With the Industry’s Choice for MLM & Network Marketing Leads. Responsive Live Leads & network marketing leads. Recruit more distributors this month and put your home business into overdrive. Our focus is creating Total Prospecting Solutions for organizations and arrangement business companies.

  25. Widipa on Octubre 28th, 2008 3:38 am

    Yo hice todo el ejemplo y me funciono de una, muchas gracias por sus aportes.

    Tengo una pregunta, como hago para que en vez de que apareca el mensaje de que debe loguarse, me redireccione de una vez a la pagina del login?.

  26. zsamer on Octubre 28th, 2008 12:42 pm

    Hola Widipa, con ZF hay dos formas dentro del controlador:

    $this->_redirect($miUrl);
    $this->_forward($action, $controller, $module, $params);

    te dejo el link en el manual oficial de ZF:
    métodos útiles en controladores

  27. fede on Noviembre 7th, 2008 10:45 am

    Muy buenas. Además de almacenar los datos del usuario, almaceno en $_SESSION los datos que a mi mi apetezca. Hasta ahí todo ok. Pero al almacenar un array obtenido como retorno de una función, me da el siguiente error:

    Fatal error: Uncaught exception ‘Zend_Session_Exception’ with message ‘Zend_Session::start() - C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca\library\Zend\Loader.php(Line:83): Error #2 Zend_Loader::include_once() [function.include]: Failed opening ‘Perfil.php’ for inclusion (include_path=’.;C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca/library;C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca/application/config;C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca/application/models;C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca/public;C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca/application/config;.;C:\php5\pear’) Array’ in C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca\library\Zend\Session.php:432 Stack trace: #0 C:\Archivos de program in C:\Archivos de programa\Apache Software Foundation\Apache2.2\htdocs\portalBiblioteca\library\Zend\Session.php on line 432

    El trozo de código donde falla es este, creo:
    $data =$authAdapter->getResultRowObject(null,’password’);
    $auth->getStorage()->write($data); $miPerfil=$auth->getIdentity()->PERFIL; $permisos=$this->model->obtenerPermisos($miPerfil);
    $_SESSION['permisos']=$permisos;

    Si meto en $_SESSION cualquier cosa funciona ok, pero al introducir el array $permisos, da ese error, alguna idea??
    gracias

  28. paolo on Enero 22nd, 2009 4:53 pm

    holas zsamer un favor, mira tengo implementado el login al estilo del tuturial y funciona bien puedo logearme hace la validadcion y me muestra los datos del usuario pero mas no puedo deslogearme osea en mi navegador siempre se quedan las cookies y no se siguen mostrando todos los datos del usuario, cual crees pueda ser mi error?
    pondre mi codigo aqui

    esto en el login controller

    public function loginAction() {
    $form = new LoginForm();
    if ($this->_request->isPost()) {
    $credentials = $this->_request->getPost();
    if ($form->isValid($credentials)) {

    try{
    $this->user->setMessage(’El nombre de Usuario y Password no coinciden.’, PersonaModel::NOT_IDENTITY);
    $this->user->setMessage(’La contraseña ingresada es incorrecta. Inténtelo de nuevo.’, PersonaModel::INVALID_CREDENTIAL);
    $this->user->setMessage(’Los campos de Usuario y Password no pueden dejarse en blanco.’, PersonaModel::INVALID_LOGIN);
    $this->user->login($credentials['username'], $credentials['password']);
    $this->_redirect(’index/login’);
    } catch(Exception $e){
    echo $responseLogin = $e->getMessage();
    $this->_redirect(’index’);
    }
    $this->view->responseLogin = $responseLogin;
    echo “erro “.$responseLogin;
    }
    }

    }

    y esto para la salida

    public function logoutAction() {
    $this->user->logout();
    $this->loggedIn=false;
    $this->_redirect(’/index’);
    }

    en el modelo de usuario

    public function login($nick, $password)
    {
    if (! empty ( $nick ) && ! empty ( $password )) {

    Zend_Loader::loadClass ( ‘Zend_Auth_Adapter_DbTable’ );

    $autAdapter = new Zend_Auth_Adapter_DbTable ( self::getDefaultAdapter () );

    $autAdapter->setTableName ( ‘persona’ );
    $autAdapter->setIdentityColumn ( ‘identificador’ );
    $autAdapter->setCredentialColumn ( ‘contrasenia’ );

    $autAdapter->setIdentity ( $nick );
    $autAdapter->setCredential ( md5 ( $password ) );
    $autAdapter->setCredentialTreatment(” AND estado=’Activo’”);
    $auth = Zend_Auth::getInstance ();
    $result = $auth->authenticate ( $autAdapter );

    switch ($result->getCode ())
    {
    case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND :
    throw new Exception ( $this->_messages [self::NOT_IDENTITY] );
    break;

    case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID :
    throw new Exception ( $this->_messages [self::INVALID_CREDENTIAL] );
    break;

    case Zend_Auth_Result::SUCCESS :
    if ($result->isValid ()) {
    $data = $autAdapter->getResultRowObject ();
    $auth->getStorage ()->write ( $data );
    } else {
    throw new Exception ( $this->_messages [self::INVALID_USER] );
    }
    break;

    default :
    throw new Exception ( $this->_messages [self::INVALID_LOGIN] );
    break;
    }

    } else {
    throw new Exception ( $this->_messages [self::INVALID_LOGIN] );
    }
    return $this;
    }
    public static function logout()
    {
    Zend_Auth::getInstance()->clearIdentity();
    Zend_Auth_Storage_Session::clear();
    Zend_Session::expireSessionCookie();
    return NULL;
    }
    hojala puedas darme una manito de todas formas te loagradesco

  29. paolo on Enero 22nd, 2009 8:07 pm

    ah por sierto uso el zf 1.7

  30. liebe on Marzo 1st, 2009 4:08 pm

    Sie haben eine sch?ne Seite!

  31. Danny on Junio 22nd, 2009 2:48 pm

    Hola que tal, queria hacer una consulta, estoy revisando este login en Zend y me corre genial, pero como seria hacer el login con autorizacíon a vaios modulo con permisos de guest, users y admins, usando Zend ACL, Auth y DB, si tuvieras una manual o tutoeial por ahi me seria de mucha ayuda. Gracias

  32. Foreverjos on Junio 30th, 2009 3:31 pm

    Hola amigos, la verdad soy nuevo en esto, un amigo tuvo el problema de:

    Fatal error: Uncaught exception ‘Zend_Session_Exception’ with message ‘Session must be started before any output has been sent to the browser; output started

    La verdad nos fastidiamos de estar buscando una salida de texto antes de iniciar la sesion, pero analizando poco a poco nos encontramos que si existia una salida de texto pero era por el error de la version del zend al usar el Zend auto Loader.

    Antes estábamos usando:

    include “Zend/Loader.php”;
    Zend_Loader::registerAutoload();

    Ahora usamos esto:

    require_once ‘Zend/Loader/Autoloader.php’;

    $loader = Zend_Loader_Autoloader::getInstance();
    $loader->setFallbackAutoloader(true);
    $loader->suppressNotFoundWarnings(false);

    El tema lo encontre aqui:

    http://phpsenior.blogspot.com/2009/05/por-actualizar-apurado-de-zf-17-18.html

    Saludos espro a alguien mas le sirva.

  33. javi on Julio 14th, 2009 12:57 pm

    Hola, felicidades por tu estupendo trabajo.

    Estoy tratando de implementar un sistema de login que puede ser llamado desde distintos módulos y la verdad es que no se como conocer desde el modulo de autenticación desde donde ha sido llamado para volver a llevar al usuario al mismo sitio.

    Un saludo.

  34. mcarrasco on Julio 21st, 2009 4:38 pm

    Hola, soy nuevo en esto de Zend Framework asi que por favor tenganme pacienca….
    Mi pregunta es la siguiente..
    He visto que para manejar los usuarios, utiliza una tabla llamada users, ¿es posible que en ves de utilizar esa tabla utilice los usuarios creados en la BBDD? es decir, en el archivo quickstart.ini el usuario que establece la conexion con la BBDD es el usuario root; como tendria que hacer para que el usuario que se conecta con la BBDD sea el ingresado en el campo nick?.
    desde ya muchas gracias.

  35. Lissette on Agosto 12th, 2009 9:57 pm

    Me gusta mucho la coleccion de tutoriales q tienes solo que no comprendo xq trabajas mucho con variables estaticas, hay un xq ?? o es te fue mas comodo trabajar con ellas. si Hay un porque pliss!! explicamelo
    saluditos

  36. caro on Septiembre 21st, 2009 8:59 pm

    Hola necesito una gran ayuda de uds.. estoy ciomenzando con zend y necesito hacer unos formularios dond cada boton tiene una funcion asociada. si alguien m puede ayudar con eso se lo agradeceria.. necesito un ejemplo para hacer esto si alguien tiene un enlace por favor.. :)

Deja tu comentario




XHTML: puedes usar estas etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>