Jan 02

Los controladores en Yii

Tagged with:
Categories: Sindicados
Estadísticas: 154 consultas Comments Off

Introducción.

Estos se ubican entre el usuario y la aplicación.  Su función es la de controlar la comunicación entre los modelos y la vistas según la solicitud (requerimiento) que ha hecho usuario.

Su clase base es CController y en ellos se implementan Acciones (definen la lógica de la aplicación) y Filtros (establecen validaciones o controles antes y después de la ejecución de las acciones).

El usuario invoca indirectamente a los controladores especificando un ruta a través del controlador frontal o Application.

La ruta del requerimiento.

El URL solicitado determina que controlador y que acción se van a ejecutar para resolver el requerimiento del usuario.

Los URL tienen el siguiente formato.

Sin URL limpias (por defecto).

http://servidor/index.php?r=ControladorId/AcciónId

Con URL limpias.

http://servidor/ControladorId/AcciónId

Si se utilizan módulos (y URL limpias para este ejemplo).

http://servidor/MóduloId/ControladorId/AcciónId

  • El archivo fuente del controlador se ubica en protected/controllers/ControladorIdController.php.
  • El nombre de la clase allí contenida deberá ser ControladorIdController.
  • Se invoca a la acción (ver mas adelante) AcciónId.  En caso de no haberse especificado una se considera la acción por defecto del controlador, comúnmente index.

Las acciones.

Pueden implementarse de dos maneras.

  • Como métodos del mismo controlador.
  • Como clases que heredan de CAction.

Acciones implementadas como métodos del controlador.

  • El nombre del método deberá ser actionAcciónId.

En el siguiente ejemplo se muestra al controlador User que implementa la acción add como un método suyo.

class UserController extends CController
{
    public function actionAdd()
    {
        // Implementación ...
    }
}

Acciones implementadas como clases independientes.

  • Los objetos acción heredan de CAction.
  • El nombre de la clase es AcciónIdAction (por convención, no es obligatorio).
  • Se almacena en un archivo bajo la ruta protected/controllers/controladorId/AcciónIdAction.php.
  • Su ubicación puede referenciarse mediante alias de esta manera: application.controllers.controladorId.AcciónIdAction.
  • Es obligatorio sobreescribir el método run() de la acción para definir allí su implementación.

En el siguiente código se muestra la acción remove del controlador User implementada como una clase independiente.

class RemoveAction extends CAction
{
    public function run()
    {
        // Implementación ...
    }
}

Esta clase se almacena entonces en el archivo protected/controllers/user/RemoveAction.php.

Como paso final de su implementación, es necesario indicarle al controlador de la existencia de la acción.  Para hacer esto es necesario sobreescribir el método actions del controlador de la siguiente manera.

class UserController extends CController
{
   public function actions()
   {
       return array(
           'remove' => 'application.controllers.user.RemoveAction'
       );
   }
}

Los filtros.

  • Permiten realizar verificaciones y validaciones antes y después de la ejecución de las acciones.
  • Una acción puede tener asociados múltiples filtros.
  • Los filtros se ejecutan en el orden en que fueron especificados.
  • Un filtro puede abortar la ejecución de los demás filtros y de la acción misma.
  • De manera análoga a las acciones, los filtros pueden implementarse de dos maneras también.
    • Como métodos del mismo controlador.
    • Como clases que heredan de CFilter.

Filtros implementados como métodos del controlador.

  • El nombre del método debe empezar por la palabra filter.
  • Deberá recibir como parámetro a $filterChain.

En el siguiente ejemplo se muestra al controlador User que implementa al filtro checkUser como un método suyo.

class UserController extends CController
{
    public function filterCheckUser($filterChain)
    {
        // Implementación ... invocar $filterChain -> run()
        // para continuar con el próximo filtro
    }
}

Filtros implementados como clases independientes.

  • Los objetos acción heredan de CFilter.
  • El nombre de la clase es FiltroIdFilter (por convención, no es obligatorio).
  • Se almacena en un archivo bajo la ruta protected/filters/FiltroIdFilter.php.
  • Su ubicación puede referenciarse mediante alias de esta manera: application.filters.FiltroIdFilter.
  • Es obligatorio sobreescribir los métodos preFilter($filterChain) y postFilter($filterChain) del filtro para definir que hacer antes y después de ejecutar la acción.

En el siguiente código se muestra al filtro isValid del controlador User implementado como una clase independiente.

class IsValidFilter extends CFilter
{
    public $admin;

    public function preFilter($filterChain)
    {
        // Se aplica antes de ejecutarse la acción.
        // Si retorna true continúa el proceso, false lo
        // aborta y no se ejecuta la acción solicitada.

        return $exito;
    }

    public function postFilter($filterChain)
    {
        // Se aplica después de ejecutarse la acción.
    }
}

Esta clase se almacena entonces en el archivo protected/filters/IsValidFilter.php.

Como paso final de su implementación, es necesario indicarle al controlador de la existencia del filtro y determinar su alcance sobre las acciones del mismo.  Para hacer esto es necesario sobreescribir el método filters del controlador de la siguiente manera.

class UserController extends CController
{
   public function filters()
   {
       return array(
           'checkUser + add, remove',

           array(
               'application.filters.IsValidFilter - add, remove',
               'admin' => false
           )
       );
   }
}
  • checkUser es un filtro basado en un método del controlador.
  • isValid es un filtro basado en una clase externa.
  • Es posible especificar los filtros con una notación de arreglo para determinar valores específicos para los atributos del filtro.

Los operadores + y - actúan como determinadores del alcance de los filtros sobre las acciones especificadas de la siguiente manera.

  • + determina exactamente a cuales acciones se les debe aplicar el filtro.  De esta manera, el filtro checkUser se aplicará a las acciones add y remove únicamente.
  • - determina a cuales acciones NO se les debe aplicar el filtro.  Así, el filtro isValid se aplicará a todas las acciones EXCEPTO a add y remove.
  • Si no se especifica ninguno de los dos modificadores, el filtro aplicará a todas las acciones del controlador.

Enlaces.

Dec 11

Redefinir una función en Javascript

Tagged with:
Categories: Sindicados
Estadísticas: 81 consultas Comments Off

Introducción.

Estaba reutilizando un formulario complejo en un nuevo módulo de mi aplicación.  Todo iba bien hasta que descubrí que uno de los códigos Javascript que actualiza parte del formulario a través de AJAX no me era útil ya que debía mostrar una vista diferente a la estándar.   Como el código estaba escrito en funciones procedimentales no podía acceder a la sobreescritura de la orientación a objetos, sin embargo encontré un par de detalles interesantes de Javascript que me permitieron hacer algo similar.

Determinar existencia de funciones.

if(typeof miFuncion == 'function')
    // Si existe la función
else
    // No existe la función

El código anterior determina si la función miFuncion ha sido definida o no en el espacio de ejecución de la aplicación Javascript.

Redefinir una función.

window['miFuncion'] = function()
{
    // Nueva implementación de la función
};

El código anterior permite redefinir la implementación de la función miFuncion la cual obviamente fue especificada anteriormente.  Lo interesante de esta sintáxis de Javascript es que esta redefinición puede realizarse de manera dinámica, es decir, en un segundo archivo *.js que se cargue después del original o inclusive dentro de un condicional.

Nov 25

Hacer algo cuando inicia o termina el evento AJAX con Prototype

Tagged with:
Categories: Sindicados
Estadísticas: 134 consultas Comments Off

Introducción.

De manera análoga a como hace poco había mostrado como manejar el evento de inicio y terminación de AJAX con jQuery para realizar algún tipo de acción específica como el mostrar un indicador de carga, ahora experimentaremos como hacerlo con el framework de Prototype el cual nuevamente estaré utilizando en el proyecto de los próximos meses.

Procedimiento.

Ajax.Responders.register({
    onCreate: function()
    {
        // An AJAX request has been initialized!
    }, 

    onComplete: function()
    {
        // An AJAX request has been completed!
    }
});

Adicionalmente hay otros eventos que pueden manejarse de igual manera onUninitialized, onLoading, onLoaded, onInteractive y onException, además de los ya mencionados onCreate y onComplete.

Enlaces.

Oct 24

Víncular los Javadocs con Netbeans

Tagged with:
Categories: Sindicados
Estadísticas: 296 consultas Comments Off

Introducción.

El siguiente procedimiento permite relacionar la documentación oficinal de Java SE (Javadocs) con Netbeans permitiéndole al desarrollador tener una mejor información mas allá de la contextual que provee por defecto el IDE.

Configuración.

Seleccione el menú Tools > Java Platforms.

p1

Seleccione la pestaña Javadoc y presione el botón Add ZIP/Folder.

p2

Seleccione el archivo ZIP o el folder donde se encuentra la documentación de los Javadoc en el equipo.

p3

Presione el botón Close para terminar la configuración.

Uso.

En el editor de código fuente seleccione la clase que desea consultar en los Javadocs y presione ALT+F1 o haga clic derecho y elija la opción Show Javadoc del menú contextual.

p4

Netbeans abrirá la documentación correspondiente a la clase solicitada en el navegador web disponible.

p5

Enlaces.

Oct 16

Ejemplo de AJAX rápido y simple con PHP y jQuery

Tagged with:
Categories: Sindicados
Estadísticas: 1,569 consultas Comments Off

Introducción.

Muy probablemente usted esté aquí, leyendo este artículo porque desea aprender a utilizar AJAX con PHP de una manera muy simple y rápida.  Yo estoy aquí porque hoy no tengo sueño y que mejor manera de esperarlo que escribir un pequeño tutorial acerca del acceso asíncrono de contenidos web utilizando el framework de jQuery.

Para no tener que dividir el artículo en varias entregas vamos a desarrollar un ejemplo muy sencillo y clásico: la calculadora, sólo que a diferencia de la habitual esta realizará sus cálculos del lado del servidor y presentará sus resultados a través de llamados con AJAX.  La implementación Javascript asociada con el objeto AJAX (el objeto XMLHTTPRequest) no la realizaremos directamente sino que utilizaremos el framework de jQuery el cual simplifica y facilita enormemente el desarrollo en Javascript.  El lado del servidor, los cálculos de nuestra calculadora, se implementarán en el viejo y conocido PHP.  Por supuesto para implementar el nivel de presentación (página web) que recibe el cliente tendremos que hablar un poco de HTML y CSS.

Qué es AJAX ?

AJAX es el acrónimo de Asynchronous JavaScript and XML, un conjunto de tecnologías web que permiten que las aplicaciones web desde sus clientes se comuniquen y soliciten información al servidor de manera asíncrona sin interferir con el contenido y comportamientos de la página actual, es decir, sin refrescar (postback) la página web por completo.

Su implementación se basa en el objeto XMLHttpRequest o XHR el cual fue originalmente desarrollado por Microsoft y apareció por primera vez en 1999 como un control ActiveX de Internet Explorer 5, posteriormente los demás navegadores lo acogieron desarrollando sus propias implementaciones.

En términos generales el uso de AJAX mejora la usabilidad de las páginas permitiendo a los desarrolladores crear aplicaciones que se comportan de manera similar a las aplicaciones de escritorio.  Un ejemplo de esto son los clientes de correo web de última generación (como GMail) y las aplicaciones geográficas (como Google Maps).  También tiene sus desventajas como presentar una mayor dificultad para su depuración, control de favoritos e historial y que los buscadores web comúnmente no pueden acceder a sus contenidos para indexarlos.

Consulte mas información acerca de AJAX en Wikipedia.

Procedimiento.

Estos son los pasos generales que realizaremos para implementar nuestra pequeña aplicación.

  1. Crear la estructura básica de la página web.
  2. Implementar el formulario de la calculadora.
  3. Mejorar la presentación del formulario.
  4. Implementar la lógica del negocio de la calculadora.
  5. Incluír una referencia a la librería de jQuery en la página web.
  6. Implementar los llamados asíncronos a la lógica del negocio de la calculadora.

La estructura básica de la página.

El primer paso es crear la estructura básica de la página web que recibirá el usuario.  Esta se puede crear con cualquier editor de texto desde el bloc de notas hasta otro mas elaborado como Dreamweaver o Eclipse PDT.  Lo importante es que sea un editor de archivos planos.  En mi caso estoy probando gPHPEdit para Linux el cual se ve hasta ahora simple y conciso.  Para el caso de Windows un editor simple como el Notepad++ servirá.

Creamos entonces el archivo calculadora.html con el siguiente contenido.

<!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>
       <!-- Documento HTML con carácteres UTF8 -->
       <meta http-equiv="Content-type" content="text/html; charset=utf-8" />

       <title>Calculadora AJAX</title>

       <!-- Clases CSS internas -->

       <!-- Referencias a Javascripts externos -->

       <!-- Código Javascript interno -->
    </head>
    <body>
        <!-- Contenido del documento -->
    </body>
</html>

He incluído algunos <!-- comentarios --> que nos servirán mas adelante para ubicar donde en el documento se deberán agregar segmentos de código adicionales.  Como se puede apreciar, esperamos ceñirnos al XHTML 1.1 transitional.

El formulario de la calculadora.

Este deberá contar con las siguientes partes básicas.

  1. Una sección para los mensajes de error (mensaje) de la aplicación.
  2. Un form (formulario) que representa al formulario en HTML.
  3. Un campo de texto (operando1) para 4 dígitos para que el usuario ingrese al primer operando.
  4. Un campo de selección (operador) para que el usuario elija la operación a efectuarse: suma, resta, multiplicación o división.
  5. Un campo de texto (operando2) para 4 dígitos para que el usuario ingrese al segundo operando.
  6. Un botón (igual) para invocar la operación de los datos.
  7. Una sección (resultado) para mostrar el resultado de la operación.

La siguiente es la implementación de esta sección y debe insertarse como el Contenido del documento en la plantilla de la estructura básica de la página web.

<div id='pagina'>
    <div id='mensaje'>&nbsp;</div>

    <form id='formulario' action='#' method='post'>
        <input type='text' id='operando1' name='operando1' value='' size='4' maxlength='4' />

        <select id='operador' name='operador'>
            <option value='SU'>+</option>
            <option value='RE'>-</option>
            <option value='MU'>*</option>
            <option value='DI'>/</option>
        </select>

        <input type='text' id='operando2' name='operando2' value='' size='4' maxlength='4' />

        <input type='button' id='igual' value='=' />

        <span id='resultado'>&nbsp;</span>
    </form>
 </div>
Nota.  El atributo del nombre (name) es requerido en los campos del formulario que se van a transmitir a través de la invocación asíncrona cuando el formulario es enviado completo como lo vamos a hacer en esta práctica.

Mejorar la presentación del formulario.

Este es el producto final de la actualización de la presentación de la página web, es necesario modificar los atributos visuales de cada una de las partes del formulario recién creado.

Interfaz de usuario de la calculadora

Interfaz de usuario de la calculadora

Las nuevas características se especifican utilizando hojas de estilo (CSS) y se referencian a través de sus identificadores, etiquetas o clases.

El siguiente código CSS realiza las modificaciones propuestas al formulario.  Estas se deben insertar en la sección de Clases CSS Internas.

<style type="text/css">

 #pagina                                       /* Envoltura general */
 {
       margin: auto;                           /* Margenes (centrado) */
       width: 600px;                           /* Ancho */
       text-align: center;                     /* Textos internos centrados */
       font-family: "arial, sans-serif";       /* Fuente del texto */
 }

 #mensaje                                      /* Mensaje de error */
 {
       width: 100%;                            /* Ancho */
       margin-top: 20px;                       /* Margen superior */
       margin-bottom: 30px;                    /* Margen inferior */
       color: #ff0e0e;                         /* Color del texto (foreground) */
       font-size: 12px;                        /* Tamaño de la fuente */
 }

 #operando1, #operando2                        /* Campos de texto de los operandos */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
       border-style: groove;                   /* Estilo del borde */
 }

 #operador                                     /* Selector del operador */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
 }

 #igual                                        /* Botón para realizar la operación */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
 }

 #resultado                                    /* Campo de texto donde se despliega el resultado */
 {
       font-size: 25px;                        /* Tamaño de la fuente */
       font-style: italic;                     /* Atributo de fuente itálica o cursiva */
 }

 </style>

La lógica del negocio de la calculadora.

El hecho de calcular el valor resultante de la operación elegida a partir de los operandos especificados es lo que llamamos la lógica del negocio.  Esta lógica, como se dijo inicialmente, la vamos a implementar en PHP en el archivo calcular.php.

Los pasos generales que deben realizarse para llevar a cabo exitosamente el cálculo del valor resultante son los siguientes.

  1. Obtener la información provista por el usuario: operandos y operador.
  2. Verificar que la información proporcionada por el usuario sea válida.
  3. Realizar la operación indicada con los valores suministrados.
  4. Mostrar el resultado.

Como veremos a continuación la implementación de estos pasos es ligeramente mas interesante que su simple mención.

Para iniciar el código PHP, le indicamos al navaegador que la respuesta del script será un texto.  Este paso específico es opcional ya que para PHP este es el tipo de respuesta por defecto.

<?php

/* Indicar el tipo de contenido que tendrá la respuesta */

header('Content-type: text/html');

La implementación de las siguientes acciones la vamos a recubrir en un bloque try/catch ya que es suceptible de generar errores y consecuentemente, lanzar excepciones.

El siguiente paso es el obtener, intentar sanear y verificar los operandos proporcionados por el usuario desde el formulario HTML.  Los parámetros fueron transmitidos a través del método post y los elementos se diferencian por su identificador.

try
{
    /* Obtener y sanear los valores de los operadores */

    $operando1 = filter_var($_POST['operando1'], FILTER_SANITIZE_NUMBER_FLOAT);
    $operando2 = filter_var($_POST['operando2'], FILTER_SANITIZE_NUMBER_FLOAT);

    /* Verificar que los valores de los operadores correspondan
       con los tipos esperados */

    if(!filter_var($operando1, FILTER_VALIDATE_FLOAT) ||
       !filter_var($operando1, FILTER_VALIDATE_FLOAT))
           throw new Exception("Operandos inválidos: [{$operando1}] y [{$operando2}]");

Realizamos una tarea similar con el operador, obtenemos su valor y verificamos que sea válido.

    /* Obtener el valor del operador */

    $operador = $_POST['operador'];

    /* Verificar que el operador suministrado sea válido */

    if(!in_array($operador, array('SU', 'RE', 'MU', 'DI')))
        throw new Exception ("Operador inválido: [{$operador}]");

Definimos una variable para almacenar el resultado de la operación solicitada.

    /* Almacenar resultado, inicialmente desconocido */

    $resultado = 0;

Realizamos la operacion correspondiente al operador recibido.  Se deben tener en cuenta dos posibles contingencias que pueden suceder: en el caso de la division, el denominador, es decir, el segundo operador no puede ser cero.  El segundo caso que debe tenerse en cuenta es que el operador recibido no corresponda con ninguna de las operaciones conocidas, esto habria sido validado inicialmente al verificar el operador suministrado despues de su recuperacion.

    /* Realizar la operación solicitada */

    switch($operador)
    {
        case 'SU':    $resultado = $operando1 + $operando2;
        break;

        case 'RE':    $resultado = $operando1 - $operando2;
        break;

        case 'MU':    $resultado = $operando1 * $operando2;
        break;

        case 'DI':    /* Verificar si el denominador es cero,
                         en ese caso, la división no puede realizarse */

                      if ($operando2 == 0)
                          throw new Exception ('División por cero');

                      $resultado = $operando1 / $operando2;
        break;

        default:      /* Si ninguna operación se ejecutó significa
                         que el operador era inválido (segunda verificación) */

                      throw new Exception('Operador desconocido');
        break;
    }
}

Para terminar la lógica de la calculadora debemos lidiar con los dos posibles resultados.  Si el procesamiento tuvo algún error (se lanzó una excepción durante el proceso) o si su terminación fue exitosa.

En caso de haber sucedido un error este se indica al usuario mediante un mensaje descriptivo y al navegador al enviarle un código 400.

catch(Exception $e)            /* La operación produjo un error */
{
    /* Indica al navegador la condición de error */

    header("Status: 400 Bad Request", true, 400); 

    /* Despliega el mensaje de error para el usuario */

    echo $e -> getMessage();

    exit(1);
}

En caso de terminar la operación exitosamente, se deberá mostrar al usuario el resultado de la misma e informarle al navegador con un código 200.

/* La operación se realizó exitosamente */

/* Indica al navegador la condición de éxito */

header("Status: 200 OK", true, 200); 

/* Despliega el resultado de la operación para el usuario */

echo number_format($resultado, 4);

exit(0);

?>

Incluír la referencia a jQuery.

En este paso lo que hacemos en incluír a la librería jQuery en nuestro proyecto web para poder utilizarla en nuestros fragmentos de código Javascript.

Para hacer esto se debe agregar la siguiente línea en la sección Referencias de Javascript externos.

<script src="http://www.google.com/jsapi"></script>
<script>google.load("jquery", "1");</script>

Este fragmento utiliza Google AJAX Libraries que nos permite incluír los principales frameworks de Javascript en nuestros sitios web sin preocuparnos por su almacenamiento o implementación, en este caso, incluír la distribución estable mas reciente de la rama 1.x.  Obviamente este método requiere que el cliente tenga acceso a Internet además de la aplicación web.

Una forma mas tradicional de hacer lo mismo es el descargar por nuestra propia cuenta la distribución de jQuery desde su sitio web, almacenar el archivo en nuestro servidor y hacer una referencia desde la página web como se muestra a continuación.

<script src='http://www.servidor.com/ruta/jquery.js' type='text/javascript'></script>

Implementar las invocaciones asíncronas.

La implementación de la invocación asíncrona se realiza directamente en Javascript utilizando a la librería jQuery recién referenciada.  Su código se agrega bajo la sección Código Javascript interno.

El primer paso que se debe realizar para su implementación es relacionar el evento de presionar el botón igual con la invocación del llamado asíncrono.  Para hacer esto vamos a utilizar un método no invasivo, es decir, no vamos a contaminar el HTML con el atributo onClick para el elemento INPUT sino que lo haremos desde el código Javascript favoreciendo la separación entre presentación/lógica del negocio y maximizando la flexibilidad de esta última.

Para hacer esto, tan pronto como se carga la página se asocia el evento de clic sobre el botón de igual para que se invoque la función procesar.

<script type='text/javascript'>

/* Código a ejecutarse tan pronto como la
   página ha sido cargada por el navegador */

$(document).ready(function ()
{
	/* Asociar el evento de clic del botón 'igual'
	   con la lógica del negocio de la aplicación */

	$('#igual').click(function()
	{
		procesar();
	});
});

El siguiente paso es la implementación de la función procesar.  En ella se realiza el llamado asíncrono a través de AJAX a la aplicación web en PHP desarrollada anteriormente para realizar el cálculo solicitado.

Una invocación asíncrona típica incluye la siguiente información básica.

  1. El URL de la aplicación web a invocarse.
  2. El tipo del requerimiento a realizarse (GET o POST normalmente).
  3. Los datos a enviarse como parámetros desde el formulario web (en formato QueryString).
  4. Definir la implementación de que hacer si la invocación es exitosa.
  5. Definir la implementación de que hacer si la invocación es fallida.

En el siguiente fragmento de código se especifican los primeros tres elementos de la lista.  El llamado asíncrono accederá a la aplicación web calcular.php mediante el método post y se le enviarán como parámetros los campos del formulario formulario.

function procesar()
{
	$.ajax ({
		url: 	'calcular.php',                   /* URL a invocar asíncronamente */
		type:   'post',                           /* Método utilizado para el requerimiento */
		data: 	$('#formulario').serialize(),     /* Información local a enviarse con el requerimiento */

En caso de ser exitoso se deberá mostrará un mensaje verde informándolo y se desplegará el resultado obtenido de la operación en la ubicación definida para este fin.

		/* Que hacer en caso de ser exitoso el requerimiento */

		success: 	function(request, settings)
		{
			/* Cambiar el color del texto a verde */

			$('#mensaje').css('color', '#0ab53a');

			/* Mostrar un mensaje informando el éxito sucedido */

			$('#mensaje').html("Operación realizada exitosamente");

			/* Mostrar el resultado obtenido del cálculo solicitado */

			$('#resultado').html(request);
		},

En caso de que la invocación sea fallida se deberá mostrar un mensaje rojo informando el error sucedido y se removerá cualquier resultado previo que pueda haber para no confundir al usuario con información anterior.

		/* Que hacer en caso de que sea fallido el requerimiento */

		error: 	function(request, settings)
		{
			/* Cambiar el color del texto a rojo */

			$('#mensaje').css('color', '#ff0e0e');

			/* Mostrar el mensaje de error */

			$('#mensaje').html('Error: ' + request.responseText);

			/* Limpiar cualquier resultado anterior */

			$('#resultado').html('Error');
		}
	});  // Fin de la invocación al método ajax
}  // Fin de la función procesar

</script>

Enlaces.

id='operador'
Oct 14

Hacer algo cuando inicia o termina el evento AJAX con jQuery

Tagged with:
Categories: Sindicados
Estadísticas: 183 consultas Comments Off

Introducción.

Este pequeño fragmento de código es muy útil, permite manipular un objeto del DOM cuando suceden los eventos de inicio o terminación del AJAX.  Muy útil para mostrar de manera fácil y automatizada un indicador de AJAX para informar al usuario que hay una transacción asíncrona en curso.

Procedimiento.

$('#loader').ajaxStart(function () {
    $(this).fadeIn();
});

$('#loader').ajaxStop(function () {
    $(this).fadeOut();
});

Adicionalmente hay otros eventos que pueden manejarse de igual manera ajaxComplete, ajaxError, ajaxSend y ajaxSuccess, además de los ya mencionados ajaxStart y ajaxStop.

Enlaces.

Oct 06

Instalación básica de Kohana 3

Tagged with:
Categories: Sindicados
Estadísticas: 400 consultas Comments Off

Introducción.

Kohana es un framework de PHP que siempre me ha parecido interesante por su simplicidad y claridad.  Inicialmente se originó como un fork de Codeigniter y posteriormente fue refinándose y alejándose un poco de este.  En lo personal me gusta mas Kohana que CI porque a pesar de ser mas jóven, me parece que han logrado consolidar mejor los recursos y la comunidad de este framework haciendo que se sienta mas sólido y mas robusto, especialmente me parece superior en su mejor orientación a objetos, soporte a PHP5 (la premisa de CI es soportar PHP4 también) y algunos módulos de core (CI tiene versiones análogas como adendos).

Tuve la oportunidad de desarrollar un proyecto con la versión 2.2 con muy buenos resultados.  A mediados del mes pasado se realizó la primera liberación estable de Kohana 3.0 que es la consolidación de la experiencia obtenida durante la serie 2.x y se constituye como una reescritura desde cero del framework.

Aún no estoy del todo seguro si me es conveniente utilizar en este momento esta nueva versión y si por el contrario permanezco con la 2.3.4 y la 2.4 próximamente.  La nueva versión difiere bastante de la existente por lo cual su API no tiene compatibilidad hacía atrás haciendo que los cambios para la actualización sean extensos y probablemente inviables.

De cualquier manera hoy me picó el gusanito de la curiosidad y ya que la documentación no será basada en un Wiki como estabamos acostumbrados sino que se generará de la documentación inline del mismo framework, acabo de instalarlo y de activar el módulo respectivo para consultarla.

La idea es instalar el framework (system/ y modules/) en un directorio por fuera del árbol público (/home/www/kohana/3.0_dev) y sólo instalar en él lo realmente relacionado con la aplicación (/home/www/public/kohana/application).

Procedimiento.

La versión convencional de este procedimiento inicia descargando la versión .ZIP de la distribución desde el repositorio del proyecto, sin embargo como mi interés primordial es el de consultar la documentación, prefiero descargar la versión mas fresca posible y esto se realiza a través del GIT del proyecto.

Descargar la distribución mas reciente de Kohana 3.

$ cd /home/www/public

$ git clone git://github.com/kohana/kohana.git

$ cd kohana

$ git submodule init

$ git submodule update

Ubicación del framework en el directorio no público.

$ mkdir -p /home/www/kohana/3.0_dev

$ mv system/ modules/ /home/www/kohana/3.0_dev

Establecer los permisos requeridos para la aplicación.

$ chmod 777 application/logs/

$ chmod 777 application/cache/

Realizar la configuración general.

$ vi index.php

$application = 'application';
$modules     = '/home/www/kohana/3.0_dev/modules';
$system      = '/home/www/kohana/3.0_dev/system';

Realizar la revisión general de requisitos.

Consultar el URL correspondiente a  http://localhost/kohana/index.php.  Si los requisitos se cumplen proceda con el siguiente paso, de lo contrario soluciónelos y vuelva a ejecutar la revisión.

$ rm install.php

Realizar la configuración general (segunda parte).

$ vi application/bootstrap.php

// Establecer la zona horaria por defecto, mas información en http://php.net/timezones.
date_default_timezone_set('America/Bogota');

// Establecer el URL base de la aplicación, por defecto es kohana donde se recupera el GIT.
Kohana::init(array('base_url' => '/kohana/'));

// Activar los módulos necesarios.  userguide es la documentación.
Kohana::modules(array(
 // 'auth'       => MODPATH.'auth',       // Basic authentication
 // 'codebench'  => MODPATH.'codebench',  // Benchmarking tool
 // 'database'   => MODPATH.'database',   // Database access
 // 'image'      => MODPATH.'image',      // Image manipulation
 // 'orm'        => MODPATH.'orm',        // Object Relationship Mapping
 // 'pagination' => MODPATH.'pagination', // Paging of results
    'userguide'  => MODPATH.'userguide',  // User guide and API documentation
 ));

// Establece el estilo de ruta y el controlador/acción por defecto.
Route::set('default', '(<controller>(/<action>(/<id>)))')
  ->defaults(array(
              'controller' => 'main',
              'action'     => 'index',
   ));

Consultar la documentación del framework.

Acceder a la URL correspondiente a la siguiente de acuerdo a las rutas exactas de instalación.

http://localhost/kohana/index.php/guide

Enlaces.

Sep 28

Como crear un mapa con GoogleMaps version 2, en pasos simples

Tagged with:
Categories: Sindicados
Estadísticas: 330 consultas Comments Off

Introducción.

Utilizar el API de Google Maps para crear mapas interactivos con Javascript en nuestros sitios web es muy fácil de implementar.  Este servicio ofrece dos alternativas: los Mapplets que se ejecutan de manera asíncrona, directamente en el sitio de maps.google.com y los desarrolladores sólo debemos especificar y albergar un documento XML donde se encuentra la especificación y los datos del mapa.  Por el otro lado están los mapas implementados directamente con el API de manera síncrona, se incrustan en nuestras propias páginas web y su comportamiento se define a través del Javascript que implementemos.

En otras ocasiones me he referido a los Mapplets por esto la implementación de hoy la vamos a realizar utilizando el API síncrono.

Objetivo.

El objetivo del presente artículo es el de visitar a Cuba donde ubicaremos marcadores sobre 5 ciudades de este país y asociaremos globitos con mensajes personalizados que aparecerán cuando el usuario haga clic sobre las diferentes ciudades.

Resultado final

Resultado final

Procedimiento.

Condiciones inciales.

Para el desarrollo de esta mini aplicación vamos a utilizar PHP y vanilla Javascript, es decir, no nos apoyaremos en ningún framework de Javascript adicional a lo comúnmente soportado por los navegadores web actuales.

En mi caso, mi servidor web de destino será http://demo.jorgeivanmeza.com/.  Es muy importante determinar esto para la próxima etapa, la creación de la llave del API.

Creación de la llave del API.

Acceda al siguiente enlace y cree su propia llave para el API de Google.  Es necesario especificar el dominio bajo el cual se ejecutará la aplicación web.  En el caso de desarrollar la aplicación de manera local, puede obtener una llave para http://localhost/ y después la deberá modificar antes de desplegarla en el servidor de producción.  Si no especifica el dominio correcto, la aplicación no podrá generar el mapa.

http://code.google.com/apis/maps/signup.html

Es necesario contar con una cuenta de Google, así que de no contar con una es necesario abrirla antes de intentar crear una llave del API.

Creación de una estructura básica para la página web.

Cree el archivo simpleGoogleMaps.php (o como desee llamarlo) en una ubicación pública de su servidor web (bajo el DOCUMENT_ROOT).  Agregue siguiente contenido al archivo y guárdelo.

<!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>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="Author" content="Jorge Iván Meza Martínez - http://jorgeivanmeza.com/ - jimezam@gmail.com" />
    <meta name="Description" content="Demostración Simple de Google Maps" />

    <title>Demostración Simple de Google Maps</title>

    <!-- Llave del API -->

    <!-- Estilos CSS -->

    <!-- Implementación Javascript -->
</head>

<body>
    <!-- Ubicación del mapa -->
</body>
</html>

Especificar la Llave del API.

En el contenido del archivo PHP actualice el siguiente código por la marca de Llave del API.

<script src='http://maps.google.com/maps?file=api&v=2&sensor=false&hl=es&key=XXXXX' type='text/javascript'></script>

Reemplace la cadena XXXXX por su Llave del API específica que obtuvo durante el paso anterior correspondiente.

Especificar la ubicación del mapa.

El mapa se generará en un div que determinemos dentro del body para tal fin, este puede estar integrado normalmente con el resto del diseño de la página.  En nuestro caso particular debido a su simplicidad, el contenido de la página será solamente dicho div.

Reemplace la etiqueta Ubicación del mapa con el siguiente código.

<div id='MiMapa'>Aqui viene el mapa!</div>

Es necesario identificar al div con un id único que utilizaremos posteriormente.

Actualizar el estilo del mapa.

El siguiente paso es el especificar un estilo para el div que contendrá al mapa.  Este estilo finalmente dependerá del diseño de la página.  Para este caso utilizamos CSS para definirle un alto y un ancho al mapa.

Reemplace la etiqueta Estilos CSS con el siguiente código.

<style content="text/css">

#MiMapa
{
    width: 640px;
    height: 480px;
}

</style>

Especificar la implementación Javascript.

El código faltante hace referencia a código Javascript que va a determinar el contenido y comportamiento del mapa.  Reemplace la etiqueta Implementación Javascript con el siguiente código base.

<script type='text/javascript'>
// El código de las siguiente secciones se incluye aquí ...
</script>

Preparar el mapa.

Para crear el mapa y establecer sus parámetros iniciales se realizan las siguientes acciones.

  1. Verificar que exista la compatibilidad adecuada con el navegador.
  2. Crear la instancia del mapa asociada al div especifico.
  3. Establecer la ubicación inicial del mapa.
  4. Establecer el tipo inicial del mapa.

Para hacer esto creamos al objeto mapa1 y a la función prepararMapa con el siguiente código.

/*
 * Objeto que hace referencia al mapa desplegado.
 */

var mapa1 = null;
/*
 * Establece los parámetros iniciales del mapa instanciando
 * al objeto 'mapa'.
 *
 * @param String  - Nombre del DIV que albergará al mapa.
 * @param Double  - Latitud donde se centrará el mapa.
 * @param Double  - Longitud donde se centrará el mapa.
 * @param Integer - Altura donde se centrará el mapa.
 *
 * @return el mapa en éxito, null en fracaso.
 */

function prepararMapa(div, centerLat, centerLang, centerAlt)
{
    /* Verifica que el navegador sea compatible con
       Google Maps */

    if (GBrowserIsCompatible())   // [1]
    {
        /* Crea la instancia del objeto 'mapa' asociándole
           el div correspondiente */

        mapa = new GMap2(document.getElementById(div));    // [2]

        /* Centra el mapa en la ubicacion (latitud, longitud
           y altura) especificadas */

        mapa.setCenter(new GLatLng(centerLat, centerLang), centerAlt);     // [3]

        /* Establece el tipo de mapa.  Disponibles:

               - G_NORMAL_MAP
               - G_SATELLITE_MAP
               - G_HYBRID_MAP

           Enlace: http://code.google.com/apis/maps/documentation/controls.html */

        mapa.setMapType(G_HYBRID_MAP);      // [4]

        /* Establece el comportamiento por defecto de los
           elementos del UI del mapa.

           Enlace: http://code.google.com/apis/maps/documentation/reference.html#GMap2.setUIToDefault */

        mapa.setUIToDefault();

        /* Éxito */
        return mapa;
    }
    else     /* Fracaso */
        return null;
}

Agregar un marcador.

Posteriormente implementamos la función agregarMarcador que se ocupará de agregar un marcador creado con cierta información específica al mapa.  Su código es el siguiente.

/*
 * Agrega un marcado con la información especificada
 * al mapa.
 *
 * @param GMap2   - Referencia externa al mapa.
 * @param Double  - Latitud donde se centrará el mapa.
 * @param Double  - Longitud donde se centrará el mapa.
 * @param String  - Mensaje que tendrá la burbuja asociada.
 *
 * @return void.
 */

 function agregarMarcador(mapa, latitud, longitud, mensaje)
 {
    /* Crea el punto asociado a la longitud y latitud
       especificadas. */

    var punto = new GLatLng(latitud, longitud);

    /* Crea un marcador asociado a la ubicación anterior */

    var marcador = new GMarker(punto);

    /* Establece que en el evento 'onclick' del marcador
       muestre la burbuja con el mensaje especificado */

     GEvent.addListener(marcador, "click", function()
     {
         mapa.openInfoWindowHtml(punto, mensaje);
     });

     /* Agrega el marcador recién creado al mapa */

     mapa.addOverlay(marcador);
 }

Información de las ciudades de Cuba.

Los marcadores del mapa corresponderán como se dijo anteriormente, con cinco ciudades de Cuba que se predefinieron y de las cuales se conoce su ubicación: latitud y longitud.  Su información se almacena en el arreglo puntos en el cual cada una de sus celdas corresponde con una ciudad.

/* Información para los marcadores del mapa: Ciudades de
 * Cuba. */

 var puntos = new Array(
    {
        'nombre'  : 'La habana',
        'latitud' : 23.132,
        'longitud': -82.364
    },
    {
        'nombre'  : 'Santa Clara',
        'latitud' : 22.4,
        'longitud': -79.967
    },
    {
        'nombre'  : 'Bayamo',
        'latitud' : 20.379,
        'longitud': -76.643
    },
    {
        'nombre'  : 'Las Tunas',
        'latitud' : 20.962,
        'longitud': -76.951
    },
    {
        'nombre'  : 'Manzanillo',
        'latitud' : 20.343,
        'longitud': -77.117
    }
 );

Para automatizar el proceso de agregación de los marcadores basados en la información de los puntos creamos a la función agregarMarcadores cuya misión es la de invocar repetidas veces a la función agregarMarcador.  En ella se define además el contenido del globito de cada uno de las ciudades (mensaje).

/*
 * Automatiza el agregar los marcadores basados en la
 * información del arreglo de puntos.
 *
 * @param GMap2   - Referencia externa al mapa.
 * @param Array   - Información de los marcadores a agregar.
 *
 * @return void.
 */

 function agregarMarcadores(mapa, informacion)
 {
    for(var i=0; i<informacion.length; i++)
    {
        var nombre   = puntos[i]['nombre'];
        var latitud  = puntos[i]['latitud'];
        var longitud = puntos[i]['longitud'];

        var mensaje  = "Este es <b>" + nombre + "</b>,<br /> su latitud es <b>" +
                       latitud + "</b><br /> y su longitud es <b>" + longitud + "</b>.";

        agregarMarcador(mapa, latitud, longitud, mensaje);
    }
 }

Finalmente, el programa principal.

En este fragmento del código definimos la ejecución del programa principal del mapa.  Se ejecuta tan pronto como la página se encuentra cargada (onLoad) y desarrolla las siguiente actividades.

  1. Prepara el mapa.
  2. Verifica que el mapa haya sido creado exitosamente.
  3. Agrega los marcadores sobre las ciudades especificadas.

Su código es el siguiente.

/* Inicio del programa Javascript (setup) */

window.onload = function()
{
    /* Solicita la creación del mapa especificando el DIV
       que lo albergará y la ubicación (latitud, longitud,
       altura). */

    mapa1 = prepararMapa('MiMapa', 21.4, -79.8, 7);

    if(mapa1 == null)
    {
        alert("Su navegador no incluye soporte para Google Maps!");

        return false;
    }

    /* Solicita la agregación de los marcadores de ejemplo
       especificando la referencia al mapa y el arreglo con
       la información de los puntos */

    agregarMarcadores(mapa1, puntos);

    return true;
}

Listo!

Probar la página web utilizando un navegador como Firefox.

Enlaces.

Sep 23

Algunas funciones del manejo de variables en PHP que acostumbro olvidar

Tagged with:
Categories: Sindicados
Estadísticas: 215 consultas Comments Off

Conversiones de tipos de datos.

  • doubleval($mixed) o floatval($mixed): convierte el valor de $mixed a su representación de punto flotante.
  • intval($mixed[, $base=10]): convierte el valor de $mixed a su representación entera en la $base especificada.
  • strval($mixed): convierte el valor de $mixed a su representación en cadena.
  • settype($mixed, $type): convierte el valor de $mixed a su correspondiente representación según el $type seleccionado.  Los $type válidos son: boolean (bool), integer (int), float, string, array, object y null.

Verificación de tipos de datos.

  • is_array($mixed): verifica si $mixed es un arreglo.
  • is_binary($mixed): verifica si $mixed es una cadena binaria nativa.
  • is_bool($mixed): verifica si $mixed es un valor booleano.
  • is_buffer($mixed): verifica si $mixed es un valor de cadena nativa binaria o Unicode.
  • is_callable($mixed): verifica si el contenido de $mixed puede invocarse como una función.
  • is_double($mixed), is_float($mixed) o is_real($mixed): verifica si $mixed es un valor real.
  • is_int($mixed), is_integer($mixed) o is_long($mixed): verifica si el contenido de $mixed es un valor entero.
  • is_null($mixed): verifica si el contenido de la variable $mixed es null.
  • is_numeric($mixed): verifica si el contenido de la variable $mixed es un número, independiente de si la variables es numérica o su representación en cadena.
  • is_object($mixed): verifica si $mixed es una instancia de una clase.
  • is_resource($mixed): verifica si $mixed es una referencia a un recurso PHP.
  • is_scalar($mixed): verifica si $mixed es un valor escalar, es decir, un entero, real, cadena o booleano.
  • is_string($mixed): verifica si $mixed es una cadena.
  • is_unicode($mixed): verifica si $mixed es una cadena Unicode.
  • gettype($mixed): obtiene el nombre del tipo de datos que representa $mixed.  Los posibles tipos de datos obtenidos son: boolean, integer, double, string, array, object, resource, NULL y unknown type.
  • get_resource_type($handle): obtiene el nombre del tipo de recurso referenciado por $handle.

Serialización de información.

  • serialize($mixed): retorna la representación serializada de $mixed.
  • unserialize($str): retorna la representación original de la variable serializada con $str.

Existencia de las variables.

  • isset($variable): verifica si la $variable ha sido definida en el contexto.
  • unset($variable): destruye la definición de la $variable en el contexto.
  • get_defined_vars(): retorna un arreglo asociativo con las variables definidas en el contexto.
  • import_request_variables($types[, $prefix]): importa las variables contenidas en GET, POST o COOKIE en el contexto actual y con el $prefix si se especificó.  Los posibles $types por ende son una cadena con las combinaciones de las letras G, P y C.

Impresión de las variables.

  • print_r($mixed[, $return]): imprime recursivamente el contenido de $mixed.  Si $return es true el resultado de la función no se imprime sino que se retorna.
  • var_dump($mixed1[, $mixed2, $mixed3, ...]): imprime recursivamente el contenido de $mixed(s) junto con su respectivo tipo de datos.
  • var_export($mixed[, $return]): imprime recursivamente la representación de la variable $mixed.  Si $return es true el resultado de la función no se imprime sino que se retorna.

Enlaces.

Sep 23

Probando Firebug Lite 1.2

Tagged with:
Categories: Sindicados
Estadísticas: 116 consultas Comments Off

Introducción.

Firebug es una de los mejores acompañantes del desarrollador web que conozco actualmente, tiene muchas funciones que facilitan enormemente el desarrollo y la depuración de las aplicaciones web.  En mi caso me facilita la revisión de problemas en cuanto a los CSS y la estructura del árbol DOM de la página se refiere, especialmente cuando se está manipulando dinámicamente con Javascript y AJAX.

Entre sus principales características se cuentan las siguientes.

  • Integración con Firefox.
  • Inspección y edición del árbol DOM y el HTML.
  • Edición en línea del CSS.
  • Visualización de las métricas del CSS.
  • Monitoreo de la actividad durante la carga de las páginas.
  • Depuración y perfil de los códigos Javascript.
  • Evaluación dinámica de código Javascript.
  • Mensajes de depuración.
  • Integración con múltiples complementos que aumentan su funcionalidad.

Esta herramienta, como se podría inferir de su nombre, ha sido desarrollada como un complemento de Firefox, lo cual acostumbra a no ser un problema ya que FF es el navegador preferido por muchos usuarios, especialmente desarrolladores y por mi.  El problema surge cuando debo iniciar Windows para probar los sitios con el -muy- problemático Internet Explorer que es ya conocido por su poco apego a las normas y estándares establecidos.  Repetir la frase "funciona perfecto con FF pero terrible con IE" es mucho mas común que la casi nunca mencionada versión inversa.

En algunas ocasiones he probado algunos complementos para IE que prometen funciones similares sin embargo he tenido poco éxito con ellas.  Hace poco leí que Microsoft estaba preparando un complemento propietario para su navegador y que permitiría realizar estas maravillas y hasta mas.

Mientras aparece una mejor opción descubrí que es posible utilizar una versión Lite (reducida) de Firebug incluye parte de las funcionalidades de la versión completa.  En mi opinión personal, incluye las tres características básicas que mas necesito y que me hacen terrible falta cuando utilizo el IE: Mejor visualización de errores (consola), Inspección de los objetos del DOM y la revisión de sus estilos CSS.

Formas de uso.

El método rápido.

Utilizando este método no es necesario modificar el código fuente de la página, este se actualiza de manera dinámica.  Es muy útil para utilizar el complemento sobre sitios que no estan dentro de nuestro control, sin embargo no permite iniciarlo desde la carga de la página por lo cual no alcanza a captar los mensajes y errores que esta genere antes de activarlo.

Para utilizar este método es necesario crear un favorito en la barra de Internet Explorer (o del navegador que se esté utilizando).

Favorito FirebugLite en IE8

Favorito FirebugLite en IE8

La dirección web de este favorito deberá estar apuntando a la siguiente invocación de Javascript.

javascript:var%20firebug=document.createElement('script');firebug.setAttribute('src','http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js');document.body.appendChild(firebug);(function(){if(window.firebug.version){firebug.init();}else{setTimeout(arguments.callee);}})();void(firebug);

Para utilizar el complemento simplemente será necesario presionar el botón del favorito (Firebug Lite) cuando se desee activarlo.

Método invasivo.

Para utilizar este método es necesario modificar el contenido de las páginas web, es decir, útil para depurar las páginas que uno mismo está desarrollando.  Para utilizarlo es necesario agregar la siguiente inclusión de código Javascript en la sección HEAD de la página.

<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>

De manera opcional es posible modificar el alto del panel de Firebug mediante la inclusión de la siguiente instrucción.

<script type="text/javascript">
firebug.env.height = 200;  // pixels
</script>

A partir del momento de la carga se cuenta con el acceso a la consola de Firebug Lite para esa página.

Ejemplo de Firebug Lite en una página web

Ejemplo de Firebug Lite en una página web

Inclusive es posible generar mensajes de depuración a la consola con instrucciones como la siguiente.

console.log("hola");

Conclusiones.

Firebug Lite es efectivamente una versión reducida de Firebug cuya principal ventaja es la de poder utilizarse con diferentes navegadores distintos a Firefox.

Las no muy extensas pruebas que he realizado hasta ahora me han mostrado algunas de sus limitaciones y diferencias con respecto a la versión completa, como por ejemplo cuando se inspecciona (Inspect) un objeto DOM a pesar de que si se actualizó la selección de la etiqueta en el árbol HTML, las propiedades que se estaban mostrando no se actualizaron hasta que hice clic sobre la el nodo HTML del componente.

En conclusión, la versión Lite no es tan completa ni poderosa como la versión completa por obvias razones, su forma de implementación, sin embargo es un gran alivio para quienes de vez en cuando tenemos que intentar depurar problemas en navegadores como IE que a juzgar por la precisión de sus mensajes, parece no ser amigo de los desarrolladores.

De momento el complemento Lite va en su versión 1.2 mientras que el complemento completo va en la 1.4.  Hay que estar pendientes de nuevas actualizaciones y mejoras.

Enlaces.