Personalizando el objeto sfUser de Symfony 2/2

Agregando inteligencia a los Flash para mensajes

Como una continuación a la serie de artículos sobre Personalizando el objeto sfUser de Symfony vamos a usar la funcionalidad “Flash” del objeto sfUser (el flash aquí no es el de adobe X-D ). Los métodos setFlash() y getFlash() en realidad usan la sesión del usuario para almacenar los datos, la única diferencia es que estos a la siguiente vez que se ejecute una redirección en la página, el mismo objeto sfUser se encarga de borrar los datos para que no permanezcan en sesión, ya que solo sirven para mostrar los mensajes una sola vez.

Con un poco de CSS podemos lograr que existan tres tipos de mensajes, trabajando un poco con los colores y algunos DIVs:

  • infoMessages: Informaciones básicas como ser “Registro grabado con éxito”, “Bienvenido usuario: Jhon Doe”, etc
  • warnMessages: Informaciones de alertas (no errores), “Usuario o clave inválida”, “El registro no pudo ser guardado por que fallo alguna validación”
  • errorMessages: Estos si son errores ocurridos en la aplicación, “No se puedo conectar a la base de datos”, “El archivo que intenta leer no existe”, etc

Por cada uno de estos mensajes vamos a crear un atributo de tipo Flash que va a contener un array para que por ejemplo si queremos mostrar más de un mensaje de tipo INFO cada uno ocupe una posición y terminemos mostrándolos todos.

Para esto vayamos al archivo %PROJECT%/apps/%APP%/lib/myUser.class.php el cual es como la extensión del objeto sfUser preparado para que lo podamos moldear nosotros, y agreguemos lo siguiente:

class myUser extends sfBasicSecurityUser
{
    const INFO_MESSAGE = 'infoMessages';
    const WARNING_MESSAGE = 'warnMessages';
    const ERROR_MESSAGE = 'errorMessages';

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    // METODOS PARA MANEJO DE MENSAJES FLASH
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    /**
     * Agrega mensajes al FLASH del objeto sfUser creando un array por cada tipo
     * de mensaje (myUser::INFO_MESSAGE, myUser::WARNING_MESSAGE, myUser::ERROR_MESSAGE).
     * El mensaje $msg será agregado al nivel correspondiente que por defecto será el INFO
     * @param string $msg
     * @param string $level
     */
    public function addMessage($msg, $level = myUser::INFO_MESSAGE)
    {
        //-- Obtengo el array almacenado, en caso de no existir retorna una array vacío
        $flashContent = $this->getFlash($level, array());

        //-- Controla si ya existe un mensaje igual para no insertarlo repetido
        if(!in_array($msg, $flashContent))
        {
            //- Agrego el mensaje enviado en la siguiente posición disponible del array
            $flashContent[] = $msg;

            //-- Seteo el array al Flash nuevamente
            $this->setFlash($level, $flashContent);
        }
    }
}

Las tres primeras líneas son constantes que se utilizarán para escribir lo menos posible los textos de los niveles. Cuando queramos, desde fuera del objeto, referirnos a ‘infoMessages’ en realidad pondremos myUser::INFO_MESSAGE. Desde dentro de la clase podremos hacerlo de la siguiente manera self::INFO_MESSAGE.

El método publico creado se va a encargar de agregar los mensajes dentro del array que será almacenado dentro del
Flash. Este método puede ser accedido desde los actions de la siguiente forma.

$this->getUser()->addMessage('Bienvenido usuario: John Doe');
$this->getUser()->addMessage('Registro grabado con éxito', myUser::INFO_MESSAGE);
$this->getUser()->addMessage('Usuario o clave inválida', myUser::WARNING_MESSAGE);
$this->getUser()->addMessage('No se puedo conectar a la base de datos', myUser::ERROR_MESSAGE);

Finalmente para mostrar los mensajes crearemos un PARTIAL global directamente dentro de la carpeta %PROJECT%/apps/%APP%/templates llamado _globalMessages.php

<?php if ($sf_user->hasFlash('infoMessages') or $sf_user->hasFlash('warnMessages') or $sf_user->hasFlash('errorMessages')): ?>

    <?php if ($sf_user->hasFlash('infoMessages')): ?>
        <?php foreach ($sf_user->getFlash('infoMessages') as $value): ?>
            INFO: <?php echo $value ?>
        <?php endforeach; ?>
    <?php endif; ?>

    <?php if ($sf_user->hasFlash('warnMessages')): ?>
        <?php foreach ($sf_user->getFlash('warnMessages') as $value): ?>
            WARN: <?php echo $value ?>
        <?php endforeach; ?>
    <?php endif; ?>

    <?php if ($sf_user->hasFlash('errorMessages')): ?>
        <?php foreach ($sf_user->getFlash('errorMessages') as $value): ?>
            ERROR: <?php echo $value ?>
        <?php endforeach; ?>
    <?php endif; ?>

<?php endif; ?>

Este partial se encarga de revisar si existen mensajes y los muestra. Ahora lo único que faltaría sería agregar en el layout de la aplicación la siguiente línea donde queramos que el partial se muestre.

<?php include_partial('global/globalMessages') ?>

Bueno de esta manera damos un poco de inteligencia el objeto sfUser trabajando en su hijo myUser y logramos automatizar una de las tareas que más se usa (o debería usarse) y nos olvidamos de tener que trabajar tanto para esto.

Para el siguiente artículo de esta serie vamos a ver como hacemos para que esta tarea sea aún más sencilla desde los actions para lo cual les recomiendo la lectura de la serie Extendiendo el sfActions de symfony.

Comenta este artículo