Extendiendo Flash Messenger Action Helper
Por zsamer en Julio 22, 2008
En este articulo vamos a ver una herramienta bastante común en el desarrollo de aplicaciones web, llamados mensajes entre request (Petición).
Comúnmente nuestros desarrollos tienen la necesidad de notificar al usuario sobre éxitos, aviso, advertencia y/o errores de un determinado proceso de nuestra lógica de negocio, es aquí donde entra en acción el Action Helper FlashMessenger, sin embargo los mensajes no los trata por separados, es decir no los clasifica según su origen (éxitos, aviso, advertencia y/o errores), si aún sigues interesado en como dar una mayor funcionalidad y potencialidad a esta herramienta éste es el articulo que estabas buscando, continua leyendo.
Un ejemplo clásico sería el siguiente:
-
try {
-
$user = $userModel->find($userId)->current();
-
-
if($user === null){
-
$this->_flashMessenger->addError('Usuario no encontrado, por favor seleccione un Id existente en la base de datos.')
-
$this->_redirect('/usuarios/index/list/');
-
}
-
-
$user->invalid_credential = ($user->invalid_credential == 0)? 1: 0;
-
$user->save();
-
$this->_flashMessenger->addSuccess('Actualización completada con éxito');
-
} catch (Exception $e) {
-
$this->_flashMessenger->addError('Error en la actualización. Por favor insista más tarde.')
-
->addError($e->getMessage());
-
}
-
-
$this->_redirect('/usuarios/index/list/');
Nos damos cuenta que el manejo de error esta bien controlado y clasificado, si ocurre algún problema ya sea que el id del usuario no exista en la base de datos o lanzó una excepción al tratar de actualizar el registro por A,B o C motivo entonces el mensaje sera clasificado como error y agregado mediante el método addError() de nuestra clase Helper Action FlashMessenger, muy por el contrario si todo salio como debiera ser entonces el mensaje será un éxito mediante el método addSuccess().
Simple y elegante, bueno la idea que propongo es extender FlashMessenger de Zend Framework para dar esta característica y además de entregarnos un output XHTML con los estilos css correspondiente al mensaje, el output sera manejado por la vista, si señor como debiera ser, a través de un Helper View.
El Helper View al cúal llamaremos FlashMessenger (obvio) tendrá la misión de imprimir la salida (render) de los mensajes con sus respectivos XHTML/CSS en nuestro(s) layout (Zend_Layout), cómo lo hará, muy sencillo llamando la instancias de nuestra clase Helper Action FlashMessenger de manera estática obtenemos los mensajes del request anterior y etc. ver más abajo.
A continuación están disponible las clases mencionadas:
Zsamer_Controller_Action_Helper_ZsamerFlashMessenger:
-
require_once 'Zend/Controller/Action/Helper/FlashMessenger.php';
-
-
class Zsamer_Controller_Action_Helper_ZsamerFlashMessenger extends Zend_Controller_Action_Helper_FlashMessenger
-
{
-
const ERROR = 'error';
-
const WARNING = 'warning';
-
const NOTICE = 'notice';
-
const SUCCESS = 'success';
-
-
/**
-
* $_namespace - Instance namespace, default is 'default'
-
*
-
* @var string
-
*/
-
protected $_namespace = 'default';
-
-
-
public function addError($message, $class = null, $method = null)
-
{
-
return $this->_addMessage($message, self::ERROR, $class, $method);
-
}
-
-
public function addSuccess($message, $class = null, $method = null)
-
{
-
return $this->_addMessage($message, self::SUCCESS, $class, $method);;
-
}
-
-
public function addWarning($message, $class = null, $method = null)
-
{
-
return $this->_addMessage($message, self::WARNING, $class, $method);;
-
}
-
-
public function addNotice($message, $class = null, $method = null)
-
{
-
return $this->_addMessage($message, self::NOTICE, $class, $method);;
-
}
-
-
protected function _addMessage($message, $type, $class = null, $method = null)
-
{
-
if (self::$_messageAdded === false) {
-
self::$_session->setExpirationHops(1, null, true);
-
}
-
-
}
-
-
self::$_session->{$this->_namespace}[$type][] = $this->_factory($message, $type, $class, $method);
-
-
return $this;
-
}
-
-
protected function _factory($message, $type, $class = null, $method = null)
-
{
-
$messg = new stdClass();
-
$messg->message = $message;
-
$messg->type = $type;
-
$messg->class = $class;
-
$messg->method = $method;
-
return $messg;
-
}
-
-
/**
-
* getMessages() - Get messages from a specific namespace
-
*
-
* @param unknown_type $namespace
-
* @return array
-
*/
-
public function getMessages($type = null)
-
{
-
if($type === null){
-
return parent::getMessages();
-
}
-
-
return self::$_messages[$this->_namespace][$type];
-
}
-
-
}
-
-
/**
-
* getCurrentMessages() - get messages that have been added to the current
-
* namespace within this request
-
*
-
* @return array
-
*/
-
public function getCurrentMessages($type = null)
-
{
-
if($type === null){
-
return parent::getCurrentMessages();
-
}
-
-
return self::$_session->{$this->_namespace}[$type];
-
}
-
-
}
-
}
Zsamer_View_Helper_FlashMessenger:
-
class Zsamer_View_Helper_FlashMessenger extends Zend_View_Helper_FormElement
-
{
-
Zsamer_Controller_Action_Helper_ZsamerFlashMessenger::ERROR,
-
Zsamer_Controller_Action_Helper_ZsamerFlashMessenger::WARNING,
-
Zsamer_Controller_Action_Helper_ZsamerFlashMessenger::NOTICE,
-
Zsamer_Controller_Action_Helper_ZsamerFlashMessenger::SUCCESS
-
);
-
-
public function flashMessenger()
-
{
-
$flashMessenger = Zend_Controller_Action_HelperBroker::getStaticHelper('ZsamerFlashMessenger');
-
-
$html = '';
-
-
foreach ($this->_types as $type) {
-
$messages = $flashMessenger->getMessages($type);
-
-
if (!$messages){
-
$messages = $flashMessenger->getCurrentMessages($type);
-
}
-
-
if ($messages) {
-
if ( !$html ) {
-
$html .= '<ul class="messages">';
-
}
-
$html .= '<li class="' . $type . '-msg">';
-
$html .= '<ul>';
-
-
foreach ( $messages as $message ) {
-
$html.= '<li>';
-
$html.= $message->message;
-
$html.= '</li>';
-
}
-
$html .= '</ul>';
-
$html .= '</li>';
-
}
-
}
-
if ( $html) {
-
$html .= '</ul>';
-
}
-
return $html;
-
}
-
}
Ejemplo de uso:
-
class Usuarios_IndexController extends Zend_Controller_Action
-
{
-
/**
-
* FlashMessenger
-
*
-
* @var Zend_Controller_Action_Helper_FlashMessenger
-
*/
-
protected $_flashMessenger = null;
-
-
public function init(){
-
parent::init();
-
//Crumbs Pendiente próximo Artículo
-
//$this->createBreadCrumbs();
-
$this->_flashMessenger = $this->_helper->getHelper('ZsamerFlashMessenger');
-
}
-
-
public function invalidCredentialAction()
-
{
-
if( !$userId = $this->getRequest()->getParam('id'))
-
{
-
$this->_flashMessenger->addError('Debe ingresar un ID de usuario válido');
-
$this->_redirect('/usuarios/index/list/');
-
}
-
-
$userModel = new User();
-
-
try {
-
$user = $userModel->find($userId)->current();
-
-
if($user === null){
-
$this->_flashMessenger->addError('Usuario no encontrado, por favor seleccione un Id existente en la base de datos.')
-
$this->_redirect('/usuarios/index/list/');
-
}
-
-
$user->invalid_credential = ($user->invalid_credential == 0)? 1: 0;
-
$user->save();
-
$this->_flashMessenger->addSuccess('Actualización completada con éxito');
-
} catch (Exception $e) {
-
$this->_flashMessenger->addError('Error en la actualización. Por favor insista más tarde.')
-
->addError($e->getMessage());
-
}
-
-
$this->_redirect('/usuarios/index/list/');
-
}
-
-
}
En nuestro layout agregamos la salida de los mensajes sobre el contenido de las acciones:
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<link rel="StyleSheet" href="/public/css/style.css" type="text/css" />
-
</head>
-
<body>
-
<div id="contenedor">
-
</div>
-
</body>
-
</html>
Finalmente el css:
-
/* MESSAGES
-
*******************************************************************************/
-
-
.error,
-
a.error span,
-
.required,
-
.validation-advice { color:#D40707 !important; font-style:bold !important; }
-
.notice { color:#ea7601}
-
.messages ul { border:0 !important; }
-
.messages li {
-
min-height:23px !important;
-
margin-bottom:11px !important;
-
padding:8px 8px 2px 32px !important;
-
font-size:.95em !important;
-
font-weight:bold !important;
-
list-style:none;
-
}
-
.messages ul li {
-
margin:0 0 3px 0 !important;
-
border:0 !important;
-
padding:0 !important;
-
}
-
.error-msg {
-
border:1px solid #f16048 !important;
-
color:#df280a !important;
-
background:#faebe7 url(../images/error_msg_icon.gif) no-repeat 10px 10px !important;
-
}
-
.success-msg {
-
border:1px solid #95a486 !important;
-
color:#3d6611 !important;
-
background:#eff5ea url(../images/success_msg_icon.gif) no-repeat 10px 10px !important;
-
}
-
.notice-msg {
-
border:1px solid #ffd967 !important;
-
background:#fffbf0 url(../images/note_msg_icon.gif) no-repeat 10px 10px !important;
-
color:#3d6611 !important;
-
}
-
.warning-msg {
-
border:1px solid #666e73 !important;
-
background:#e6e6e6 url(../images/warning_msg_icon.gif) no-repeat 10px 10px !important;
-
color:#000000 !important;
-
}
Y por supuesto, nos faltaba agregar las imágenes o iconos representantes de los mensajes:
Imagen de ejemplo de éxito
Imagen de ejemplo de error
Espero que sea de utilidad, personalmente lo encuentro muy funcional y ágil para el manejo de errores de nuestra aplicación, bueno y también de éxitos, advertencias, avisos.
Lamentablemente hemos llegado al fin de nuestro articulo pero nos vemos en el próximo igual que siempre
.
Comentarios
33 Responses to “Extendiendo Flash Messenger Action Helper”
Deja tu comentario



Muy buen artículo, como siempre.
Tendremos que agregarlo a los proyectos “surforce”
PD: ya te iba a mandar un email ya que hacía demasiado tiempo que no leía un post nuevo de tu autoría
Gracias Enrique, como siempre es un gusto compartir conocimiento.
Hola,
me da el siguiente error:
Fatal error: Uncaught exception ‘Zend_View_Exception’ with message ‘helper ‘FlashMessenger’ not found in path’ in C:\xampp\htdocs\aptana\inmo\library\Zend\View\Abstract.php:1004 Stack trace: #0 C:\xampp\htdocs\aptana\inmo\library\Zend\View\Abstract.php(497): Zend_View_Abstract->_loadClass(’helper’, ‘FlashMessenger’) #1 C:\xampp\htdocs\aptana\inmo\library\Zend\View\Abstract.php(294): Zend_View_Abstract->getHelper(’flashMessenger’) #2 [internal function]: Zend_View_Abstract->__call(’flashMessenger’, Array) #3 C:\xampp\htdocs\aptana\inmo\application\views\scripts\admin\properties.phtml(12): Zend_View->flashMessenger() #4 C:\xampp\htdocs\aptana\inmo\library\Zend\View.php(46): include(’C:\xampp\htdocs…’) #5 C:\xampp\htdocs\aptana\inmo\library\Zend\View\Abstract.php(769): Zend_View->_run(’.\application\v…’) #6 C:\xampp\htdocs\aptana\inmo\library\Zend\Controller\Action\Helper\ViewRenderer.php(907): Zend_View_Abstract->render(’admin/propertie…’) #7 C:\xampp\htdocs\aptana\inmo\library\Zend\Controller\Action\Helper\ViewRender in C:\xampp\htdocs\aptana\inmo\library\Zend\View\Abstract.php on line 1004
Al parecer no encuentra el método flashMeseenger(), alguna solución?
Saludos.
Hola Langos,
Tienes que crear un Namespace(directorio) en la carpeta library, puedes llamarlo como quieras luego ahí mantienes la misma estructura de Zend, es decir en el caso de agregar un helper view tendrías que dentro de tu namespace crear un sub directorio View y luego Helper.
Ejemplo: library\Zsamer\View\Helper (Zsamer es mi Namespace donde guardo las clases que heredo de Zend Framework y además para agregar los helpers action y/o helpers view, plugins etc…).
Bueno, en la carpeta Helper guardas todos los Helper View tales como Zend_View_Helper_FlashMessenger.
Finalmente y lo más importante tienes que decirle a Zend_View que tenga en cuenta el nuevo Namspace de Helpers:
$this->view->addHelperPath(Core::getBaseDir() . DIRECTORY_SEPARATOR . ‘library/Zsamer/View/Helper’, ‘Zsamer_View_Helper_’);
eso sería en todo caso en el manual de Zend Framework explica más detallado esto.
saludos.
Hola,
muchas gracias, ya lo he solucionado.
Saludos.
Hola Andrés !
Para que funcionara tuve que agregar Zend_Controller_Action_HelperBroker::addHelper( new Zsamer_Controller_Action_Helper_ZsamerFlashMessenger() ); en el bootstrap, creo q es correcto asi que lo dejo aca por si le sirve a alguien mas.
Saludos
lisandro, es muy valido tu aporte, ahora también hay otra manera, es la que uso yo: se defina en el bootstrap:
Zend_Controller_Action_HelperBroker::addPrefix(’Zsamer_Controller_Action_Helper’);
En el fondo le dice a Zend que debe de tomar en cuenta mi namespace donde voy a guardar mis propios Action Helper, en este caso el namespace o carpeta sería “Zsamer/Controller/Action/Helper”.
Luego en el controlador haces esto:
$helperFlash = $this->_helper->getHelper(’ZsamerFlashMessenger’);
Inmediatamente chequea si existe la instancias, si no existe busca la clase en el namespace por defecto de zend y si no esta la busca en el namespace que definimos en el paso anterior y la crea, luego retorna la nueva instancia.
Ok, entonces de esta forma no tengo registrar uno a uno todos mis (tus ;)) helpers …mucho mejor.
Sospechaba que habia una mejor manera de hacerlo por eso la inquietud.
Gracias otra vez, saludos !
jeje, claro justamente eso es, se registra sólo una vez.
saludos.
Te animas a subir el codigo??
¿subir el código? es un articulo, tienes que leerlo y ahí están las clases y ejemplos que necesitas, no necesitas que te suba ningún código.
Realmente te felicito por tus articulos, estan super interesantes. Pero tengo serios problemas con las estructuras y los nombres de las clases y sus ubicaciones, por eso te comentaba, la idea de que puedas subirlas.
saludos. gracias
@francisco: Fijate que el nombre de las clases generalmente te dice la ruta, reemplaza los underscore (_) por / o \ y te va a dar la ruta
Zsamer, muy bueno, ya lo hice andar en mi sistema, si agrego algo te paso la actualizacion
[...] no va a ser el definitivo, pero necesitaba una estructura para trabajar. También incorpore el plugin de Zsamer para el manejo de errores. El login ya tomo un poco de forma, y solucionamos algunos problemas con las [...]
Hola,
Lo primero enohrabuena por tu web y tus artículos que son de gran ayuda.
Tengo un pequeño porblema con el flasMessenger. Cuando muestro un msg, al pinchar en un enlace e ir a otra parte de la web me mantiene el msg en pantalla (sólo en el primer clic después de mostrar un msg en los sucesivos ya no, hasta que vuelvo a mostrar otro msg que vuelve a pasar) es como si quedase cacheado el msg y no lo borrase después de mostrarlo ¿os pasa a vosotros también?
No hay que pinchar ningún enlace, agregas los mensajes pertinentes y luego haces un:
$this->_redirect(’/usuarios/index/list/’);
No no, si el problema es que una vez mostrado el msg en pantalla, por ejemplo:
“Registro de cuenta de usuario realizado.”
Al pinchar en el menú login para iniciar sesión, me mantiene en pantalla el msg, es decir, una vez mostrado el msg en pantalla, vaya donde vaya después (dentro de mi aplicación claro) me vuelve a mostrar el msg sin haberlo generado de nuevo.
No se si me explico…
Bueno, creo que lo he “solucionado”, el problema era que en el indexController habia mostrado los distintos tipos mensaje para ver su aspecto y por algún motivo me los dejaba cacheados de algún modo y por eso se mostraban mal.
Un saludo.
[...] Extendiendo Flash Messenger Action Helper [...]
Hola,
Muchas gracias, justo lo que necesitaba. Buen trabajo!
En su momento también tuve problemas con los menajes, estos no se borraban y se mostraban el la accion siguiente, lo solucioné usando $this->_helper->redirector->goto(); en vez de $this->_redirect(), no tengo claro el motivo todavia pero lo dejo por si le sirve a alguien.
Tengo el problema de duración de los mensajes en pantalla, la cuestión es que lo estoy usando en la validación de formularios, pero no quiero perder los datos (cosa que sucedería si hago el redirect), cómo lo podría solucionar? me podéis ayudar?
puedes utilizar un $this->_forward(),
Estoy siguiendo todos los tutoriales que publicas y parecen geniales. Con respecto a este quisiera saber que lineas de codigo, exactamente, van en el bootstrap, y como definir ese namespace ? Muchas gracias.
download mp3 music unashamed, mp3 treble charger dowload the road to sourceville mp3 switchfoot mp3 download free still lives perry blake mp3 songs sukhbir mp3 free downlaod scott bradley tom and jerry
hola, tengo el bootstrap en el archivo Core.php, pero noc en que parte tengo que poner:
Zend_Controller_Action_HelperBroker::addPrefix(’Zsamer_Controller_Action_Helper’);
ya que lo he puesto en varios lugares pero sigue saliendo el error:
Message: Action Helper by name ZsamerFlashMessenger not found
espero q me puedan ayudar,, graciaass
Holas.. estuve siguiendo todo el tuto y hasta ahora me ha ido todo bien, pero en este tuto, me he perdido.. no se como probar el ejemplo..
trate de hacer algo asi http://localhost/quickstart/public/usuarios
pero me sale este mensaje
http://localhost/quickstart/public/usuarios
no se si habria la posibilidad de que publiques tus archivos de este ejemplo solamente porfa..
gracias de antemano..
Edito. mi comentario anterior, el mensaje que me muestra es este :
Message: Action Helper by name ZsamerFlashMessenger not found
disculpen la confusion..
pero podrian ayudarme!!
si coloco esto en el boostrap
$this->view->addHelperPath(Core::getBaseDir() . DIRECTORY_SEPARATOR . ‘library/Zsamer/View/Helper’, ‘Zsamer_View_Helper_’);
me da el siguiente error:Fatal error: Using $this when not in object context in /var/www/sis/index.php on line 36
Finalmente y lo más importante tienes que decirle a Zend_View que tenga en cuenta el nuevo Namspace de Helpers: como realizo esto y donde lo coloco
Hola una consulta, como puedo trabajar una applicacion con acceso a 2 bases de datos distintas, postgresql y mysql.
Thanks
Such individuals can be produced when two equal recessive mutants happen to be crossed with each other or when a mutant is crossed with itself; this is possible in hermaphroditic plants and even happens spontaneously. ,
Hola,
muy buena la extensión. Lo que no acabo de entender es la existencia y la creación de una clase stdClass del método _factory.
¿ Me lo podría alguien explicar para qué se usa ?
Gracias