lunes, 12 de diciembre de 2011

Chequear si se ha iniciado una sesión en PHP

Para iniciar una sesión en PHP, utilizamos la función session_start(), sin embargo, una práctica común (no necesariamente buena siempre) es forzar a que las sesiones se inicien automáticamente, modificando el archivo de configuración php.ini, especificamente haciendo session.auto_start = 1.

Bueno, el problema es que si ejecutamos session_start() y ya se encuentra una sesión activa (porque hayamos invocado anteriormente session_start() o porque se inicien automáticamente por nuestro php.ini), a partir de la versión 4.3.3 de PHP, se imprimirá un horrible mensaje tipo Notice:


Notice: A session had already been started - ignoring session_start()


Lo correcto es que invoquemos session_start() sólo si es necesario. Para ello, utilizaremos la función session_id(), la cual devuelve una cadena correspondiente al id de la sesión actual o una cadena vacía si no hay una sesión iniciado. Un posible uso sería:

<?php
if (strlen(session_id()) < 1)

  session_start();
?>



lunes, 5 de diciembre de 2011

Gestión de Máquinas Virtuales por Cónsola

En varias entradas anteriores he escrito un poco sobre máquinas virtuales en Linux, utilizando KVM/Qemu y Virt-Manager. En los últimos tiempos las he estado utilizando para simular una pequeña red de 4 computadores, en la que 3 de ellos son virtuales y se utilzan como un clúster de balanceo de carga (1 nodo director y 2 servidores reales).

El manejo de GUIs con Virt-Manager es realmente sencillo, más sin embargo, se desperdician muchos recursos si queremos tener las interfaces de 3 máquinas virtuales, para simplemente editar uno que otro archivo. En esta entrada, voy a mostrar algunos de los comandos virsh más comunes para la gestión de MVs mediante la consola.

Arrancar una Máquina Virtual es tan sencillo como:
virsh -c qemu:///system start nombre_maquina

Para arrancar automáticamente una MV al bootear:
virsh -c qemu:///system autostart nombre_maquina

Apagar una MV:
virsh -c qemu:///system shutdown nombre_maquina

Para listar las MVs que están corriendo en el sistema:
virsh -c qemu:///system list

Para reiniciar una MV:
virsh -c qemu:///system reboot nombre_maquina

Guardar el estado de una maquina virtual (y detenerla):
virsh -c qemu:///system save nombre_maquina nombre-20111205.state

Restaurar una MV a partir de un estado guardado:
virsh -c qemu:///sysem restore nombre-20111205.state


Con estos comandos es más que suficiente para realizar las tareas básicas de gestión. Y por supuesto, si lo que necesitamos es conectarnos a una cónsola para realizar alguna tarea sobre una MV, pues nada, ahí está el comando SSH ;)




miércoles, 16 de noviembre de 2011

jQuery: Cómo saber si un objeto pertenece a una clase

Supongamos que estamos iterando sobre una serie de elementos del DOM con jQuery y que realizaremos algunas operaciones dependiendo de la clase a la que pertenezca cada elemento. ¿Cómo saber si un elemento pertenece a una determinada clase?

Sencillo, utilizando la función is() de jQuery. Por ejemplo:

if ($(#elementoID).is('.nombreclase')) {
  alert('pertenece a la clase nombreclase');
} else {
  alert('No pertenece a la clase nombreclase');
}

Además, el argumento que recibe is(), puede ser básicamente cualquier expresión, por lo que podemos preguntar cosas como: is(":first-child"), is(":contains('Peter')"), etc.

Reseteando botones JQuery UI

Tenemos un pequeño formulario en el que incluímos algunos radios hechos con jQueryUI Button. Por alguna razón, en algún momento queremos resetear dichos radios (de manera que ninguno esté seleccionado o que esté seleccionado alguno en específico). Hacemos lo obvio: recorremos los radios y ponemos checked = false a todos (y opcionalmente checked = true al que queremos quede seleccionado). Acto seguido, nos damos cuenta que no sirve.

Más concretamente, el campo checked si se actualizará, pero no así la parte gráfica. Cada vez que cambiemos los Buttons de jQueryUI, necesitamos refrescarlos para que también se actualice la apariencia.

El método clave para esto es "refresh", que según la documentación oficial "Refreshes the visual state of the button. Useful for updating button state after the native element's checked or disabled state is changed programatically."

Invocarlo sobre cualquier botón es muy sencillo, por el ID, sería algo como:

  $('#botonId').button("refresh");


Por poner un segundo ejemplo, yo tengo una función en javascript para limpiar formularios que invoco después de hacer envío de formularios via Ajax. Para resetear todos los radios, sólo tendría que incluir en esta función las siguientes líneas:

$('input:radio').each(function() {
  $(this).button("refresh");
});


Vale, eso es todo. Sencillo

viernes, 7 de octubre de 2011

Jugando con KumbiaPHP


Aunque ya he trabajado con KumbiaPHP en este blog, me tomaré unas 2 o 3 entradas, a manera de tutorial para explicar algunos aspectos del framework.

KumbiaPHP es un framework sumamente sencillo de usar y sobre todo práctico, implementa el patrón MVC y es además muy liviano, comparado con otros frameworks populares.

Otras razones para utilizar KumbiaPHP: está escrito en español, por hispanohablantes y se caracteriza por ser muy muy rápido. Aquí un benchmarking para comparar rendimiento con algunos frameworks.

Lo primero que debemos hacer es descargar la librería. Al momento de escribir este tutorial, la última versión oficial es la v1.0 Spirit, que se puede descargar desde la web. Sin embargo, mi recomendación es uitlizar la versión de desarrollo, que se encuentra en una fase estable y contiene muchas mejoras con respecto a la v1.0. Esta última, podemos descargarla del repositorio en launchpad. Es con esta versión que trabajaré en lo sucesivo.

Bien, luego de descargar, descomprimimos el archivo en nuestro directorio web y obtendremos la siguiente estructura:

kumbiaphp/
|--core
|--default
|--.htaccess

Para verificar que todo vaya bien, en un navegador vamos a la url de nuestro site, y debería mostrarse la página de bienvenida de kumbia.

Ahora detallemos un poco los directorios que vienen por omisión.

En core encontraremos todos los archivos del framework. En core/vendors están todas las bibliotecas externas que utiliza kumbia (es aquí donde debemos colocar cualquier biblioteca que necesitemos), y en core/libs están las bibliotecas desarrolladas/mantenidas por kumbia.

Con la descarga, viene un directorio default, el cual contiene una aplicación que sería la aplicación por omisión. Al mismo nivel de default podemos crear todas las aplicaciones que querramos.

En lo sucesivo trabajaré con default, pero repito, podemos crear otros directorios si queremos. Dentro de default, encontramos 2 subdirectorios: default/app y default/public. En el primero irá el core de nuestra aplicación, mientras que en el segundo almacenaremos todos los recursos (imágenes, scripts, hojas de estilo, archivos flash, etc) que se utilizarán en las páginas webs de nuestra aplicación.

En default/app/config están los archivos de configuración de nuestra aplicación. En default/app/models, default/app/views y default/app/controllers estarán los modelos, vistas y controladores.

Dentro de views/_shared/templates, está la plantilla por defecto: default.phtml (se usará en todas las vistas en las cuales no especifiquemos otra plantilla). En view/_shared/templates podemos guardar todas las plantillas que queramos y utilizarlas cuando sea necesario.


Un poco sobre MVC

No se trata de un tutorial del patrón MVC, así que daré sólo los detalles necesarios. Cada controlador está implementado como un archivo con nombre nombre_controller.php en el subdirectorio app/controllers. Por ejemplo, si queremos un cotrolador "principal", crearemos un archivo principal_controller.php. Este archivo es básicamente una clase, de nombre nombreController, heredada de AppController, con una serie de métodos públicos, que serían las acciones de nuestro controlador.

Por cada controlador, debe existir un subdirectorio en app/views con el mismo nombre de nuestro controlador. Por cada acción debe existir un archivo con extensión .phtml en este subdirectorio. Por ejemplo, si nuestro controlador principal tiene las acciones bienvenida y despedida, en app/views crearemos un directorio principal, que debe contener los archivos bienvenida.phtml y despedida.phtml.

La siguiente imagen, tomada del wiki de kumbia muestra cual es la relación entre controladores/acciones y URLs:



Esto si core y default están en el directorio raiz del directorio web del servidor. En nuestro caso, no es así, sino que están dentro de otro directorio que creamos dentro del directorio web del servidor y que hemos llamado kumbiaphp, por lo que nuestras rutas serían del tipo http://dominio/kumbiaphp/controller/action.

Sin mayor preámbulo, creamos nuestro primer controlador (principal_controller.php):

<?php 
class PrincipalController extends AppController {
    public function bienvenida() 
    {
        $this->bienvenida = "Bienvenido a KumbiaPHP";
    }

    public function despedida() 
    {
        $this->despedida = "Vuelve pronto";
    }
}
?>

Nuestra primera vista (bienvenida.phtml):

<h1>KumbiaPHP</h1> 
<p><?php echo $bienvenida ?></p>

Y nuestra segunda vista (despedida.phtml):

<h1>KumbiaPHP</h1> 
<p><?php echo $despedida ?></p>

Ahora si en el navegador vamos a http://localhost/kumbiaphp/principal/bienvenida o http://localhost/kumbiaphp/principal/despedida, veremos los mensajes correspondientes a cada vista.

Debemos notar que aunque en las vistas sólo hay un par de líneas, en el navegador se ve nuestro contenido, enmarcado en la plantilla por omisión (default.phtml). Podemos modificar o sustituir esta plantilla por una nuestra. Sólo debemos tener presente 2 cosas:
  • No debemos eliminar la línea <?php View::content(); ?>, pues esa es la instrucción que le dice al framework que muestre el contenido propio de la vista (y en qué lugar dentro de la plantilla hacerlo).
  • La sintaxis para la inserción de contenido, que explicaré a continuación.


Incluyendo contenido en una plantilla

Bien sea que sustituyamos default.phtml, o que creemos una nueva plantilla, tenemos que saber como se incluyen ciertos elementos en nuestras vistas, a través de los numerosos helpers que provee el framework.

Para incluir correctamente archivos css:

<?php Tag::css('wide-blue/style') ?>
<?php echo Html::includeCss() ?>

Esto supone que tenemos un archivo style.css, y está ubicado en el subdirectorio app/public/css/wide-blue.

Para incluir imágenes:

<?php echo Html::img("lvbp.jpg"); ?>

Para incluir enlaces:

<?php echo Html::linkAction("enlace", 'Titulo') ?>

Para que estos helpers funcionen, debemos recordar que debemos guardar las imágenes, css y javascripts en los directorios correspondientes dentro de app/public.

En la próxima entrega...

De momento, con esto es suficiente para que elaboremos una o más plantillas y dejemos el entorno a punto para trabajar. Ya sabemos que para enviar información del controlador a la vista, basta con definir en el último, una variables $this->nombre_variable y luego en la vista podremos accederla como $nombre_variable. No hemos hablado de modelos porque no ha sido necesario, lo haremos en la siguiente entrega, al igual que el pase de datos desde las vistas hacia los controladores.




miércoles, 5 de octubre de 2011

martes, 4 de octubre de 2011

Bloquear interfaz con jQuery

Sigo en la onda de jQuery, esta vez con un plugin muy útil cuando trabajamos con ajax.

Es una práctica muy común hoy en día, realizar solicitudes POST o GET mediante ajax, de esta forma no tenemos que recargar la página completa cada vez, sino una pequeña parte de la misma.


Seguramente hemos visto en algun sitio que cuando subimos una foto a un servidor o realizamos alguna consulta, toda la interfaz se bloquea y aparece en medio un mensaje que nos informa que la página está realizando alguna tarea, que esperemos.

Esto se hace por 2 motivos. El primero es informarle al usuario que ya se está procesando su solicitud; el segundo, que viene a ser consecuencia del primero, es evitar el doble envío de data. Si por ejemplo lo que el usuario está realizando es una búsqueda compleja y no se le informa que ya se está procesando, al pasar unos segundos, el usuario puede pensar que el navegador no "agarró" la orden y volver a presionar el botón de envío, e inclusive hacerlo varias veces al no ver respuesta. Peor aún, si se trata de una inserción en base de datos, la data podría estar insertándose varias veces, lo cual sería fatal.

Bloqueando la interfaz, resolvemos los 2 problemas: le informamos al usuario que su solicitud se está procesando y a la vez protejemos nuestra aplicación de múltiples envíos de data. Esto le da además un comportamiento síncrono a nuestras aplicaciones asíncronas.

¿Cómo lo hacemos? Bien, con un poco de manejo del DOM y CSS podemos lograr el efecto, sin embargo, para jQuery ya existen varios plugins para hacerlo de forma realmente simple. Uno de ellos, se llama BlockUI, y su uso es tan sencillo como incluir el plugin, por supuesto, y luego lo usamos de la siguiente forma.

Para bloquear la pantalla:

$.blockUI({ message: '<h1><img src="busy.gif" /> Por favor espere...</h1>' });

Para desbloquear la pantalla:

$.unblockUI();

Si queremos que la interfaz se bloquee, cada vez que hacemos una solicitud ajax y se desbloquee al terminarla:

$(document).ajaxStart($.blockUI).ajaxStop($.unblockUI);

Supongamos que tenemos un formulario para buscar datos de clientes y mostrarlos en una tabla. Con jQuery ponemos un manejador al submit del formulario, para que realice la búsqueda por POST via ajax e incruste el código HTML de la tabla en un DIV que tengamos destinado para tal fin, podemos bloquear/desbloquear la interfaz de la siguiente manera:

<script type="text/javascript">
$(function() {
	$('#formulario').submit(function() {
		var url = $(location).attr('href');
		var key = $('#keyword').val();

		$.blockUI({ message: '<h1><img src="busy.gif" /> Por favor espere...</h1>' });

		$.post( url,
		{ search_key: key },
			function(data){
			var datos = $('#divdatos');
			datos.html(data);
			$.unblockUI();
		});
		return false;
	});
});
^lt;/script>

Si queremos que la interfaz se desbloquee después de cierto tiempo, podemos hacerlo con la función setTimeout:

setTimeout($.unblockUI, 2000);


Como siempre, recomiendo ir directamente a la fuente y revisar todos los demos, que se pueden hacer muchas más cosas.