Mar 31

Introducción.

De vuelta a Mootools, fue el primero de los frameworks de Javascript que utilicé hace un poco mas de un año.  Después he experimentado un poco mas con Prototype/Scriptaculous y ahora estoy empezando a leer un poco acerca de jQuery.  Sin embargo siempre me ha gustado Mootools y es hora de documentar, tal y como se hizo con Prototype, como se realizan los llamados asíncronos (AJAX) con él.

En este artículo voy a describir las cuatro maneras como es posible realizar llamados con AJAX utilizando MooTools.

  1. El método load de los elementos.
  2. El método Request.HTML.
  3. El objeto Request directamente.
  4. El método Request.JSON.

1. El método load de los elementos.

Este método lo tienen los elementos (componentes) de Mootools.  Es muy útil porque permite actualizar rápidamente cualquier elemento con el contenido HTML retornado por un llamado asíncrono.  A pesar de ser muy fácil de utilizar, carece de las opciones y la flexibilidad de los métodos siguientes, por ejemplo, del paso de parámetros.

Para hacer uso de este método se utiliza la siguiente instrucción.

$('componente').load(urlRemota);

Donde componente es el elemento que se desea actualizar (un div por ejemplo) y urlRemota es el URL que se invoca de manera asíncrona para obtener el código HTML con el que se reemplazará el contenido del elemento.

Para más información acerca de este método consultar la documentación de Request.HTML.

2. El método Request.HTML.

Este método es una facilidad implementada sobre el método analizado a continuación.  Permite obtener el mismo objetivo del método anterior con una mayor flexibilidad.

    var myHTMLRequest = new Request
        .HTML({
            url:       urlRemota,
            update:    'componente',
            method:    'post',
            data:      $('formulario'),

            onRequest: function()
            {
                // Al iniciar la solicitud.
            },

            onComplete: function(html)
            {
                // Al completarse la solicitud.
            },

            onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript)
            {
                // Si la solicitud se completó exitosamente.

                /*
                   responseTree - (element) The node list of the remote response.
                   responseElements - (array) An array containing all elements of the remote response.
                   responseHTML - (string) The content of the remote response.
                   responseJavaScript - (string) The portion of JavaScript from the remote response.
                */
            },

            onFailure: function(elemento)
            {
                // Si la solicitud se completó con problemas.
            }
        })
        .send();

De manera similar al método anterior, el atributo url define el URL que se invocará para obtener de manera asíncrona el código HTML para actualizar el elemento referenciado por el atributo update.  El atributo method define si se utilizará POST o GET para la invocación del llamado.

El resto de atributos son opcionales.   El atributo data permite especificar variables que van a ser incluídas con el requerimiento.  Pueden especificarse como un query string de la forma "var1=valor1&var2=valor2", como un hash de la forma {"var1": "valor1", "var2": "valor2"} o enviando un formulario por completo de la forma $('id_formulario').

Los atributos onXXX son manejadores de eventos a manera de callbacks y son ejecutados según lo que acontezca durante la solicitud del llamado asíncrono.

  • onRequest: ha sido iniciado el proceso de la solicitud.
  • onComplete: la solicitud ha terminado.
  • onSuccess: la solicitud ya ha terminado y terminó exitosamente.
  • onFailure: la solicitud ya ha terminado y terminó de manera fallida.

Para más información acerca de este método consultar la documentación de Request.HTML.

3. El objeto Request directamente.

Esta es la forma mas flexible de utilizar AJAX con MooTools ya que permite realizar la solicitud y manipular que se desea hacer con el resultado obtenido, ya no necesariamente actualizar un elemento.

    var myRequest = new Request({
        url:    urlRemota,
        method: 'post',
        data:   $('formulario'),

        onRequest: function()
        {
            // Al iniciar la solicitud.
        },

        onComplete: function(html)
        {
            // Al completarse la solicitud.
        },

        onSuccess: function(responseText, responseXML)
        {
            // Si la solicitud se terminó exitosamente.

            /*
                responseText - (string) The returned text from the request.
                responseXML - (mixed) The response XML from the request.
            */

            // Aquí se implementa que hacer con la respuesta del llamado asíncrono
            // cuando el procedimiento fue exitoso.

            /*
                Actualizando manualmente el componente,
                reproduce la funcionalidad de Request.HTML:

                $('componente').set('html', responseText);
            */
        },

        onFailure: function(xhr)
        {
            // Si la solicitud se completó con problemas.

            /*
                xhr - (XMLHttpRequest) The transport instance.
            */

            // Aquí se implementa que hacer con la respuesta del llamado asíncrono
            // cuando el procedimiento fue fallido.
        },

        onCancel: function()
        {
            // La solicitud fue cancelada.
        },

        onException: function(headerName, value)
        {
            // La transmisión de la cabecerá falló.

            /*
                headerName - (string) The name of the failing header.
                value - (string) The value of the failing header.
            */
        }
    }).send();

Se incluyen dos manejadores de eventos adicionales.

  • onCancel: la solicitud ha sido cancelada.
  • onException: la transmisión de la cabecera (header) provocó una excepción.

Se incluyen además, entre otras cosas, la propiedad running que permite verificar si el objeto myRequest se encuentra o no actualmente procesando una solicitud y al método cancel() que permite cancelar la solicitud activa, generando consecuentemente un evento de cancelación (ver onCancel).

Para más información acerca de este método consultar la documentación de Request.

4. El método Request.JSON.

Es una facilidad construída sobre el objeto Request que permite manipular respuestas de llamadas asíncronas en formato JSON (Javascript Object Notation).

    var jsonRequest = new Request.JSON({
        url:    urlRemota,
        method: 'post',
        data:   $('formulario'),

        onRequest: function()
        {
            // Al iniciar la solicitud.
        },

        onComplete: function(responseJSON)
        {
            // Al completarse la solicitud.
        },

        onSuccess: function(responseJSON, responseText)
        {
            // Si la solicitud se terminó exitosamente.

            /*
                responseJSON - (object) The JSON response object from the remote request.
                responseText - (string) The JSON response as string.
            */

            /*
                La información recibida del llamado asíncrono se puede obtener como atributos
                del objeto responseJSON, por ejemplo acceder a responseJSON.nombres
            */
        },

        onFailure: function(xhr)
        {
            // Si la solicitud se completó con problemas.

            /*
                xhr - (XMLHttpRequest) The transport instance.
            */
        }
    }).send();

Para más información acerca de este método consultar la documentación de Request.JSON.

Ejemplo funcional.

La aplicación de ejemplo obtiene información dinámica del servidor de manera asíncrona, para actualizar los campos DIV de la página utilizando cada una de las cuatro técnicas descritas en este artículo.

Para la generación de la información dinámica del lado del servidor se utilizaron dos scripts muy simples desarrollado en PHP, uno de ellos genera una cadena constante junto con la fecha actual y el otro prepara la respuesta JSON a partir de la información recibida.  Además muestra la información recibida a través del POST.  El script ContenidoRemoto.php es utilizado para los métodos 1, 2 y 3 mientras que el script Contenido RemotoJson.php es utilizado para el método 4.

Para consultar el ejemplo funcionando en el servidor de demostración se debe seguir este enlace.

Para consultar el código fuente de cada uno de los archivos que componen el ejemplo se deben seguir los enlaces dispuestos a continuación: index.php, ContenidoRemoto.php y ContenidoRemotoJson.php.

Enlaces.

Tagged with:



En March 31 de 2009, Jorge Iván Meza Martínez escribió acerca de Introducción al AJAX con Mootools 1.2.1.
Mar 28

Hace ya algún tiempo trate de probar una version de desarrollo del software para la creación de mundos virtuales de Sun Microsytems Wonderland, hace poco entre de nuevo al sitio y me encontré que había salido el release 3 de la version 0.5, asi que lo descargue y probé su funcionamiento con Ubuntu 8.10

Requermientos :

  • Tener el JDK instalado en Ubuntu
  • Tener el Ant instalado en Ubuntu

Pasos :

  • Abrir una consola
  • Ir al directorio donde se almacenara el software, por ejemplo sw
    cd sw
  • Descargar utilizando subversion la version 0.5 release 3,
    reemplazar <username> por el usuario de java.net :
    svn checkout https://wonderland.dev.java.net/svn/wonderland/tags/0.5-dev3 wonderland --username <username>
  • Esperar un tiempo relativamente largo mientras se descarga todo el software
  • Cambiar al directorio donde se almaceno el wonderland
    cd wonderland
  • Compilar la aplicacion
    ant
  • Iniciar el servidor
    ant run-server
  • Luego de iniciarse el servidor aparece la dirección web donde se debe entrar para iniciar el cliente, por ejemplo :
    http://192.168.122.1:8080/
  • Abrir el navegador y entrar a la dirección web
  • Pulsar el botón Launch Wonderland 0.5
  • El servidor envía un archivo que se debe abrir con el Sun Java 6 Web Start
  • Se abre una caja de dialogo para solicitar permiso para ejecutar la aplicacion
  • Se abre la ventana principal y se abre una caja de dialogo para suministrar el usuario, nombre completo y servidor
  • Suministre los datos y pulse el botón login
  • Espere unos momentos mientras se carga el mundo.

Pruebas Wonderland 0.5 Dev Release 3

Problemas :

  • Al momento de tratar de mover el avatar las teclas del cursor no funcionaron.
  • La aplicación inexplicablemente dejo de funcionar y el avatar no se movió mas.

Enlaces :

Tagged with:



En March 28 de 2009, Marlon J. Manrique escribió acerca de Ejecutando Wonderland v0.5 Release 3.
Mar 27

bliptv_upload_tool

Si se desea subir un archivo de video muy grande a Blip.tv o muchos archivos, es mejor utilizar una aplicacion que permita hacer la descarga de forma directa sin necesidad de utilizar un navegador, para esto Blip.tv afortunadamente provee una utilidad que permite desde Linux y utilizando Java subir los archivos.

Requisitos :

  • Tener instalado Java o instalarlo
  • Abrir una consola, ejecutar
    sudo apt-get install sun-java6-jdk
  • Verificar que el Java6 sea la alternativa por defecto
    sudo update-alternatives --config java

Pasos :

  • Ir a la pagina de herramientas de Blip.tv
    http://blip.tv/tools
  • Descargar el archivo para Linux
    http://blip.tv/UpperBlip.jar
  • Si desea ejecutar directamente desde el escritorio :
    • Visualizar el directorio donde se guardo el archivo
    • Click derecho en el archivo UpperBlip.jar
    • Seleccionar la opción Open with "Sun Java 6 Runtime"
  • Si desea ejecutar desde consola (esta aplicación es gráfica)
    • Abrir una consola
    • Ir al directorio donde se almaceno el archivo
    • Ejecutar el siguiente comando
      java -jar UpperBlip.jar
  • Suministrar el nombre de usuario y clave
  • Autenticarse
  • Seleccionar el o los archivos a subir
  • Suministrar la información de los archivos
  • Subir el archivo

Enlaces :

Tagged with:



En March 27 de 2009, Marlon J. Manrique escribió acerca de Subiendo Archivos a Blip.tv desde Ubuntu.
Mar 27

mysql_logoAl momento de instalar MySQL en Ubuntu 8.10 la configuracion por defecto solo permite conexiones desde la maquina donde esta instalado el servidor, para permitir a clientes remotos acceder a la base de datos del servidor, se debe quitar la reestriccion de acceso solo local.

Pasos :

  • Abrir una consola en el servidor donde esta instalado el MySQL
  • Editar el archivo de configuracion
    sudo vi /etc/mysql/my.cnf
  • Buscar la linea
    bind-address           = 127.0.0.1
  • Comentar la linea, adicionando un # al principio de la misma
    #bind-address           = 127.0.0.1
  • Reiniciar el servidor de MySQL
    sudo /etc/init.d/mysql restart

Nota :

Recuerde adicionar los usuarios de tal modo que se puedan conectar desde otra maquina o desde cualquier maquina, esto se realiza con la sentecia SQL GRANT que permite especificar el nombre de la maquina desde la cual se conectara el usuario o utilizar % para permitir el acceso desde cualquier maquina.
Ejemplo :
GRANT ALL PRIVILEGES ON *.* TO 'usuario'@'%' IDENTIFIED BY 'clave';
Esto permite el acceso a el usuario a cualquier base de datos desde cualquier equipo.

Enlaces :

Tagged with:



En March 27 de 2009, Marlon J. Manrique escribió acerca de Clientes Remotos MySQL en Ubuntu 8.10.
Mar 25

Hasta ahora no he encontrado una solución para resaltar la sintáxis de segmentos de código en Wordpress.  Hasta la fecha he utilizado varios plugins con resultados parcialmente exitosos.

El primero que probé fue CodeHighlighterPlugin de IdeaThinking.com.  Es simple, resalta la sintáxis de múltiples lenguajes y opcionalmente permite mostrar un número de línea.  Para señalar el código a resaltar se debe encerrar entre etiquetas <pre lang="XXXX" lineno="1">...</pre>.

Después encontré a varios blogs que resaltaban el código de manera mas elegante, con segmentos que coloreaban las líneas y permitían cambiar entre vista enrriquecida y vista plana así como copiar al portapapeles.  Encontré entonces al Google Syntax Highlighter for WordPress de Peter Ryan.  Soporta menos lenguajes (no incluye a bash por ejemplo) sin embargo es mi favorito hasta el momento.  Para segmentar el código a resaltar se debe encerrar entre etiquetas <pre name="code" class="XXXX">...</pre>.

El problema hasta ahora es que TinyMCE, el editor WYSIWYG de Wordpress, es felíz borrándome los atributos de los pre convirtiéndo mis fragmentos de código en invisibles para el resaltador haciendo que cada vez que edite o cree un artículo con códigos tenga que editar los textos de manera visual y después tenga que corregir las etiquetas de manera HTML.  Es infame!

Buscando una mejor opción ante este problema encontré el plugin SyntaxHighlighter2 de S H Mohanjith el cual hábilmente utiliza una sintaxis BBCode para segmentar el código a resaltar:  [source language='XXXX']...[/source].

Sin embargo le encontré un problema colateral al plugin: al no utilizar etiquetas pre, el editor/navegador no respetan los espacios en blanco que contenga el código a su izquierda, es decir, se ignora la identación.  El autor muy amablemente me sugirió copiar y pegar los códigos desde el modo HTML sin embargo esto es lo que precisamente quiero evitar.

Anoche, ante la imposibilidad de encontrar una mejor solución y mi testarudez, tuve una idea: utilizar el plugin de Peter Ryan el cual no funciona como quisiera porque el editor le remueve el atributo name y agregárselo de manera dinámica cuando cuando la página se ha desplegado en el cliente.

Hoy me dí manos a la obra y encontré que Wordpress utiliza jQuery así que investigué como manipular el evento onLoad, obtener todas las etiquetas pre y como agregarles el atributo name='code' faltante.  El siguiente fue el resultado.

<script type='text/javascript'>
jQuery(document).ready(function() {
    jQuery('pre').each(function () {
         jQuery(this).attr('name', 'code');
    });
});
</script>

Por razones aún desconocidas no pude hacer funcionar el plugin en el onLoad también para que se encolaran los códigos y terminaran ejecutándose secuencialemente cuando el árbol DOM estuviera listo.  Como alternativa modifiqué apropiadamente el archivo fuente del plugin que inserta el script en la página del blog.

En wp-content/plugins/google-syntax-highlighter/google_syntax_highlighter.php agregué las siguientes líneas al final del código.

<script class="javascript">
/* sección de código agregada */
jQuery('pre').each(function () {
        jQuery(this).attr('name', 'code');
});

/* código ya existente en el archivo */
dp.SyntaxHighlighter.ClipboardSwf = '<?php echo $current_path; ?>Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
</script>

Aún tengo que utilizar el módo HTML o utilizar el botón Insert/Edit Attributes de TinyMCE para indicarle a las etiquetas pre cual es el lenguaje de su contenido (class), sin embargo ya no tengo que preocuparme por el atributo name ni porque este sea borrado cada vez que edite al artículo.

Enlaces.

Tagged with:



En March 25 de 2009, Jorge Iván Meza Martínez escribió acerca de Resaltando la sintáxis de códigos en WordPress.
Mar 19

Controladores.

  • Actúa como intermediario entre el requerimiento del usuario y, los modelos, las vistas y otros recursos que generan su respuesta.
  • Su clase base es Controller.
  • Su identificador empieza con minúsculas: user.
  • El nombre de su clase empieza con mayúsculas: User.
  • El nombre de archivo coincide con el identificador y la extensión .php.
  • Se almacenan bajo application/controllers.  Es posible agrupar controladores en subdirectorios, estas rutas se deberán ver reflejadas en el requerimiento del usuario.
  • Si se define un constructor para el controlador: __construct para PHP5, su primera instrucción deberá ser invocar al constructor padre: parent::Controller().
  • Las acciones (o funciones) corresponden con los métodos del controlador y es allí donde se implementa su lógica.
  • Los nombres de las acciones comienzan con minúsculas.
  • Las acciones pueden recibir información adicional del requerimiento de usuario a través de sus parámetros.
  • El controlador por defecto es welcome, esto personalizarse modificando el valor de $route['default_controller'] en application/config/routes.php.
  • La acción por defecto es index.
  • Los controladores y las acciones por defecto son utilizadas si el usuario no las referencia explícitamente en su requerimiento.
  • Para definir métodos privados en el controlador que no serán tomados en cuenta como acciones, deberán declararse como private o protected (PHP5) y su nombre deberá empezar por un guión-bajo (PHP 4 y 5).
  • Es posible personalizar la manipulación de las acciones de un controlador sobreescribiendo el método _remap($method) del último.  No es frecuente hacerlo.
  • Es posible manipular, como postprocesar, la información que va a ser enviada de regreso al usuario desde un controlador sobreescribiendo su método _output($output).  No es frecuente hacerlo.

// Archivo application/controllers/user.php

class User extends Controller
{
	public function __construct()
	{
		parent::Controller();
		// Constructor del controlador.
	}

	public function index()
	{
		// Acción por defecto.
	}

	public function changeName($firstName, $lastName)
	{
		// Acción con parámetros enviados desde el requerimiento.
	}

	private function _myInternalMethod()
	{
		// Método privado no acción.
	}
}

Vistas.

  • Se encarga de preparar y organizar la información resultante que será presentada al usuario como respuesta a su requerimiento.
  • Son archivos con contenido XHTML y PHP.
  • No son invocados directamente, son utilizados por los controladores.
  • El nombre de su identificador puede ser arbitrario.
  • El nombre del archivo será su identificador junto con la extensión .php.
  • Se almacenan bajo application/views.  Es posible agrupar vistas en subdirectorios, estas rutas se deberán ver reflejadas en su llamado desde el controlador.
  • Para cargar una vista desde el controlador: $this -> load -> view('ruta/archivo').  La extensión de la vista puede omitirse si se utilizó la extensión por defecto.
  • Este método envía inmediatamente el contenido de la vista procesada al usuario.
  • Es posible enviar información desde el controlador hacia la vista modificando su carga: $this -> load -> view('ruta/archivo', $data).
  • $data puede ser un arreglo relacional o un objeto.  En el primer caso, las celdas del arreglo se convierten en variables de la vista siendo el índice de cada celda el nombre y el contenido su correspondiente valor de la variable.  De igual manera ocurre en el segundo caso, convirtiéndose en variables de la vista a los atributos del objeto.
  • Es posible cargar una vista y almacenarla en una variable para su posterior uso en lugar de enviarla directamente al usuario: $myView = $this -> load -> view('ruta/archivo', $data, true).

// Archivo application/controllers/user.php

class User extends Controller
{
	public function index()
	{
		$data['title'] = "System Administration";
		$data['suibtitle'] = "User management";

		$this -> load -> view('user/index', $data);
	}
}

// Archivo application/views/user/index.php

<html>
	<head>
		<title>< ?php echo $title; ?></title>
	</head>
	<body>
		<h1>< ?php echo $subtitle; ?></h1>
	</body>
</html>

Modelos.

  • Representan a la lógica del negocio y la información del sistema.
  • Su clase base es Model.
  • Su identificador empieza con minúsculas: user.
  • El nombre de su clase corresponde con el identificador empezando con mayúsculas y terminando con el postfijo _model: User_model.
  • El nombre de archivo coincide con el nombre de la clase en minúsculas y la extensión .php: user_model.php.
  • Se almacenan bajo application/models.  Es posible agrupar modelos en subdirectorios, estas rutas se deberán ver reflejadas en el momento de invocarlos.
  • Si se define un constructor para el modelo: __construct para PHP5, su primera instrucción deberá ser invocar al constructor padre: parent::Model().
  • Para cargar un modelo desde el controlador: $this -> load -> model('ruta/Nombre_modelo').  Esto comúnmente se realiza en el constructor de la clase que lo utiliza para garantizar su uso a todo su largo.
  • Después de cargado el modelo puede utilizarse de la siguiente manera: $this -> Nombre_modelo -> método().
  • Es posible especificar el nombre del objeto donde se cargan los modelos: $this -> load -> model('ruta/Nombre_modelo', 'otroNombre'), esto permite acceder a él de la siguiente manera: $this -> otroNombre -> método().
  • Un tercer parámetro enviado durante la carga de un modelo le permite a este autoconectarse a la base de datos del sistema: $this -> load -> model('ruta/Nombre_modelo', '', true).
  • Es posible indicarle al framework que cargue automáticamente una lista de modelos al listarlos en el arreglo $autoload['model'] de application/config/autoload.php.

// Archivo application/controllers/user.php

class User extends Controller
{
	function __construct()
	{
		parent::Controller();
		$this -> load -> model('admin/user');
	}

	public function index()
	{
		$data['info'] = $this -> User -> miMetodo();

		$this -> load -> view('user/index', $data);
	}
}

// Archivo application/models/admin/user.php

class User_model extends Model
{
	function __construct()
	{
		parent::Model();
	}

	public function miMetodo()
	{
		// Implementación de la lógica del negocio
	}
}

Requerimiento del usuario.

  • El requerimiento del usuario incluye la información que encapsula su solicitud, así como todos los datos requeridos interpretarla.
  • La información proviene desde dos fuentes: el URL (dirección) y el contenido POST (formularios).
  • El URL por defecto sigue este formato: server.com/index.php/controller/action/data1/data2.  Cada parte del URL es conocida como un segmento.  Los segmentos controller y action corresponden con los identificadores del controlador y de la acción, incluyendo las rutas adicionales si se utilizaron, que son requeridos por el usuario.
  • Los segmentos adicionales (data1 y data2) son pasados a la acción como parámetros del método.
  • La información enviada a través de variables POST, como es el caso de los formularios, es recibida a través de la clase Input de la seiguiente manera: $this -> input -> post('nombreVariable', true).  El segundo parámetro (booleano) indica si la variable debe ser o no pasada por el filtro XSS de contenido antes de ser accedida.

Enlaces.

Tagged with:



En March 19 de 2009, Jorge Iván Meza Martínez escribió acerca de Introducción al MVC de CodeIgniter – Parte I.
Mar 18

Introducción.

CodeIgniter es un framework muy interesante para el desarrollo de aplicaciones web.  Lo he estado utilizando por dos años y ha sido muy útil.  Su curva de aprendizaje no es muy pronunciada lo que ha facilitado que desarrolladores no muy experimentados lo aprendan a usar rapidamente.  Su misión es la de proveer una base para el desarrollo de aplicaciones web con PHP brindándonos una serie de herramientas y estructuras facilitadoras que, gracias a su arquitectura desacoplada, no son obligatorias ni restringen el uso de facilidades de terceros.  Es un framework general, es útil y flexible, y no es el mas complejo o restrictivo del mercado.

Ventajas tiene muchas, algunas de las cuales ya he mencionado: fácil aprendizaje, flexible, desacoplado, buen desempeño en términos de tiempo de ejecución y consumo de memoria, muy utilizado y bien documentado.  En pocas palabras, utilizar CodeIgniter le permitirá desarrollar PHP de la misma forma como lo realizaba anteriormente pero de una manera mas estructurada y con algunas herramientas que le permitirán agilizar su implementación.

Como desventajas se encuentra el hecho de que su desarrollo recaiga sobre un sólo hombre, Derek Allard, haciendo que su proceso de actualización fuera lento en comparación con los deseos de la comunidad; sin embargo he estado leyendo un poco acerca de que ahora es un grupo de personas quienes lideran el desarrollo del framawork motivo por el cual me imagino que esto ha cambiado.  Una desventaja muy mencionada es su empeño por seguir soportando PHP4 además de PHP5 impidiéndole tomar ventaja de las mejoras que trajo el lenguaje en su última versión.  Otro punto en contra de CodeIgniter es que podría mejorarse su orientación a objetos en varios aspectos (probablemente producido por lo mencionado anteriormente), por ejemplo, los ayudantes (helpers) son en realidad una librería de funciones.

Por estos motivos un subconjunto de sus seguidores decidió hacer un fork del proyecto para implementar su propias mejoras.  Este fue el nacimiento de Kohana.  Con este nuevo framework estoy desarrollando un proyecto desde hace unos seis meses y su implementación ha sido muy placentera, aunque no se si por las mejoras en el framework o por lo la calidad y lo interesante del proyecto.  Sobra decir que la migración de CodeIgniter a Kohana es un proceso indoloro.  Pero no todo es color de rosa, actualmente la principal ventaja de Kohana es su propio punto débil: su comunidad activa y ávida de mejoras realiza modificaciones al framework frecuentemente haciendo que, según leo en los foros, la próxima versión que saldrá en el presente año no será compatible con versiones anteriores, haciendo que en este momento no sea idónea para desarrollar proyectos a largo plazo.  CodeIgniter por su parte a probado ser bastante estable y a documentar los cambios necesarios para actualizar sus versiones, que de paso no sobra decirlo, siempre es conveniente mantenerse al día con la última versión disponible.

Obtención del framework.

El objetivo de este paso es el de obtener los archivos de la distribución mas reciente de CodeIgniter que se va a instalar.

$ cd /home/www

$ wget http://codeigniter.com/download.php

Instalación del framework en una ubicación privada.

Como se mencionó, el framework se instalará en una ubicación privada y podrá ser compartido por múltiples aplicaciones.  Se crea un enlace dinámico (current) para facilitar la actualización de versiones del framework.

$ unzip CodeIgniter_1.7.1.zip

$ rm CodeIgniter_1.7.1.zip

$ mkdir codeigniter

$ mv CodeIgniter_1.7.1 codeigniter/1.7.1

$ cd codeigniter

$ ln -s 1.7.1/ current

Creación de una aplicación de prueba.

Esta aplicación de prueba deberá mostrar al usuario el controlador (welcome) y la vista (welcome_message) que trae por defecto CodeIgniter.

$ cd /home/www

$ mkdir public/Demo1

$ cp -rf codeigniter/current/system/application/* public/Demo1

$ cp codeigniter/current/index.php public/Demo1

$ rm public/Demo1/index.html

Configuración del controlador frontal de la nueva aplicación.

Es necesario indicarle al controlador frontal de la aplicación donde encontrar a la distribución del framework (system) y donde encontrar los archivos de la aplicación (application).

$ vi public/Demo1/index.php

error_reporting(E_ALL);

$system_folder = "/home/www/codeigniter/current/system";

$application_folder = "/home/www/public/Demo1";

Verificación del funcionamiento inicial del sitio.

Si los pasos anteriores fueron exitosos, si se consulta el sitio web deberá obtenerse un página similar a la siguiente.  Téngase en cuenta que deberá reemplazarse el nombre del servidor (localhost) por el que sea necesario si este no se encuentra en su mismo equipo.

Visitar con un navegador web la siguiente dirección.

http://localhost/Demo1/

Enlaces.

Tagged with:



En March 18 de 2009, Jorge Iván Meza Martínez escribió acerca de Instalación de CodeIgniter 1.7.x en Linux.
Mar 18

laconica_logoHace poco instale Laconica en mi sitio web para tener un historial completo de las entradas que voy actualizando de lo que estoy haciendo, esto lo hice en mi proveedor de hosting Dreamhost. Hasta el momento todo habia funcionado bien, pero ahora que queria conectar Ping.fm con mi Laconica la cosa no funciono.

Resulta que Laconica implementa el API de Twitter para permitir a aplicaciones de terceros poder puplicar entradas en el microblog, para esto es necesario realizar una validacion del usuario a traves de Autenticacion Basica, la cual es soportada por PHP solamente cuando esta instalado como modulo y no como CGI como esta instalado en Dreamhost.

Asi que si necesita utilizar la verificacion de usuario de Laconica en un sitio basado en Dreamhost no es posible sin cambiar alguna configuracion o incluso cambiar la forma de validacion del usuario.

Enlaces :

Tagged with:



En March 18 de 2009, Marlon J. Manrique escribió acerca de Laconica en Dreamhost.
Mar 15

Introducción.

Anoche se me ocurrieron algunos experimentos para hacer pero con varios de ellos terminé concluyendo que necesitaba hacer algunas búsquedas a través de Google Search para verificar si mis hipótesis se podían implementar o no.  Pensé que iba a ser muy fácil encontrar ejemplos de esto en PHP, sin embargo sólo pude encontrar un documento realmente interesante al respecto.  Resulta que casi toda la documentación hace referencia a Javascript en AJAX, mientras que los lenguajes no-Javascript como PHP o Flash deben hacerlo a través de REST.  Al final, mis ideas no resultaron; al parecer Google no genera la información que yo necesitaba en formato Google Search, tampoco en XML válido.  Sin embargo aprendí como utilizar Google Search desde PHP y terminé escribiendo una clase muy sencilla para encapsular su uso y una demostración de la misma.

Demostración.

Demostración de GoogleSearch 0.1

Demostración de GoogleSearch 0.1

GoogleSearch.class.php.

De manera muy general estos son los pasos que se deben realizar para ejecutar una búsqueda en GoogleSearch.

Crear una instancia de la clase GoogleSearch.

    $gs = new GoogleSearch();

Establecer la configuración de la búsqueda.

    $gs -> setKey('SU_PROPIA_LLAVE');
    $gs -> setSize('large');
    $gs -> setLang('es');
    $gs -> setReferrer('http://localhost');
    $registro = (isset($_GET['registro'])) ? filter_input(INPUT_GET, 'registro', FILTER_SANITIZE_SPECIAL_CHARS) : 0;
    $palabrasClave = (isset($_GET['palabrasClave'])) ? filter_input(INPUT_GET, 'palabrasClave', FILTER_SANITIZE_SPECIAL_CHARS) : '';

Solicitar la búsqueda.

    $gs -> fetch($palabrasClave, $registro);

Verificar si hubo éxito en la búsqueda.

    if($gs != null && $gs -> getResponseField('responseStatus') == 200) { ... }

Recorrer los registros obtenidos y mostrar su información.

                $length = $gs -> getResultsCount();

                for($i=0; $i<$length; $i++):

                    // Obtiene el iésimo resultado.

                    $result = $gs -> getResult($i);

                    // Muestra su información.
                ?>

                    <tr>
                        <td>
                            <a href='<?= GoogleSearch::getResultField($result, 'url'); ?>'>
                                <?= GoogleSearch::getResultField($result, 'title'); ?>
                            </a>
                            &nbsp;
                            <a href='<?= GoogleSearch::getResultField($result, 'url'); ?>' target='_blank'>
                                [<span style='font-size: 10px;'>Nueva ventana</span>]
                            </a>
                        </td>
                    </tr>
                    <tr>
                        <td class='campo_contenido'>
                            <?= GoogleSearch::getResultField($result, 'content'); ?>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <span class='verde'><?= GoogleSearch::getResultField($result, 'visibleUrl'); ?></span> -
                            <a href='<?= GoogleSearch::getResultField($result, 'cacheUrl'); ?>'>En caché</a>
                        </td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                    </tr>

                <?php endfor; ?>

Enlaces.

Tagged with:



En March 15 de 2009, Jorge Iván Meza Martínez escribió acerca de Búsquedas en Google Search desde PHP.
Mar 11

Hoy tuve la necesidad de serializar objetos en PHP para implementar la funcionalidad de cache de las series basadas en los indicadores de un proyecto que estoy realizando y que, de paso, cada día me está quedando mas interesante.

Se me ocurrieron dos opciones, una fueron las funciones de serialización de objetos convencionales que incluye PHP y otra fue utilizar la representación JSON de mis datos para enviarlos y recibirlos de la persistencia, en este caso, archivos de texto.  Finalmente me decidí por utilizar las funciones de serialización sobre las de JSON por dos diferencias funcionales que en este proyecto eran ventajosas.

  • JSON sólo incluye a los atributos públicos, en mi caso eran protegidos.
  • Al recuperar la información en formato JSON y convertirla a objeto PHP nuevamente los datos son recuperados como objetos genéricos, no del tipo exacto como se codificaron.  Las funciones de serialización no tienen este problema.

Las funciones de serialización son muy simples: serialize y unserialize.

  • La primera de ellas recibe el objeto a serializar y retorna su representación en cadena.
    string serialize (mixed)
  • El segundo recibe la representación en cadena del objeto serializado y retorna el objeto PHP correspondiente.
    mixed unserialize (string)

Funcionan perfecto.  Todo fue demasiado sencillo.  Como siempre, en el mundo de Murphy, había un problema.  A los objetos que debía serializar el framework que utilizaba (Kohana) les estaba agregando un atributo protegido llamado db donde se encontraba la información de conexión a la base de datos, incluyendo la contraseña y por ende esta información estaba quedando serializada en mis archivos de caché!  Conclusión: un problema de seguridad terrible y un tamaño sensiblemente mayor para estos archivos.

Los objetos a serializar eran modelos con cierta complejidad de anidamiento de entidades (algunos atributos eran objetos también) por lo cual no era una opción muy interesante el realizar la serialización por mi mismo recorriendo recursivamente las estructuras de datos.  Tampoco pude acceder a los objetos para borrarles (unset) los atributos extra.

Por suerte las funciones de serialización incluyen una facilidad para estos casos.  Internamente se llaman automáticamente los métodos mágicos __sleep justo antes de la serialización y __wakeup justo después de la desserialización.

Mas interesante aún, el método __sleep puede retornar un arreglo con los nombres de los atributos que serán efectivamente incluídos en la serialización de los objetos de dicha clase.  Para remover entonces el atributo db de la serialización sólo tuve que hacer lo siguiente.

    public function __sleep()
    {
        $atributosSerializables = get_object_vars($this);
        unset($atributosSerializables['db']);
        return array_keys($atributosSerializables);
    }
Tagged with:



En March 11 de 2009, Jorge Iván Meza Martínez escribió acerca de Serialización de objetos con PHP.