<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>HiperGalaxia &#187; php</title>
	<atom:link href="http://www.hipergalaxia.org/blog/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hipergalaxia.org/blog</link>
	<description>El conocimiento, la frontera final.</description>
	<lastBuildDate>Thu, 09 Sep 2010 02:16:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Degradar PHP 5.3 a 5.2 en GNU/Linux Ubuntu 10.04</title>
		<link>http://blog.jorgeivanmeza.com/2010/07/degradar-php-5-3-a-5-2-en-gnulinux-ubuntu-10-04/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=degradar-php-5-3-a-5-2-en-gnulinux-ubuntu-10-04</link>
		<comments>http://blog.jorgeivanmeza.com/2010/07/degradar-php-5-3-a-5-2-en-gnulinux-ubuntu-10-04/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=degradar-php-5-3-a-5-2-en-gnulinux-ubuntu-10-04#comments</comments>
		<pubDate>Wed, 14 Jul 2010 02:56:47 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[5.2]]></category>
		<category><![CDATA[5.3]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[downgrade]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Linux/Solaris/BSD]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=4951</guid>
		<description><![CDATA[Introducción. La versión mas reciente de Ubuntu, Lucid Lynx (10.04), incluye en sus repositorios por defecto la versión 5.3 de PHP la cual trae consigo una serie de modificaciones considerables que hacen que muchas de las aplicaciones requieran algún tipo de modificaciones para funcionar correctamente. Mientras se realizan estas modificaciones para actualizar las aplicaciones sea [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>La versión mas reciente de Ubuntu, Lucid Lynx (10.04), incluye en sus repositorios por defecto la versión 5.3 de PHP la cual trae consigo una serie de <a href="http://php.net/manual/es/migration53.php" >modificaciones considerables</a> que hacen que muchas de las aplicaciones requieran algún tipo de modificaciones para funcionar correctamente.</p>
<p>Mientras se realizan estas modificaciones para actualizar las aplicaciones sea hace necesario continuar utilizando las aplicaciones existentes y para esto se debe reemplazar la versión instalada de PHP por la versión mas reciente de la serie anterior (5.2.x).  La migración no es trivial debido a que los paquetes vienen directamente de los repositorios, sin embargo si se utiliza el <em>script</em> provisto opr <a href="http://mrkandy.wordpress.com/" >KAndy</a> el proceso se simplifica enormemente.</p>
<h2>Instalación de PHP.</h2>
<p>Si aún no cuenta con PHP instalado en el equipo puede realizar una instalación básica mediante la ejecución de la siguiente instrucción.  Instale los demás paquetes que considere necesarios.</p>
<p><span style="font-family: courier new,courier;">$ sudo aptitude install apache2 php5 php5-cli php5-mysql</span></p>
<p>En este punto el equipo tendrá instalado PHP 5.3 y es el momento de degradarlo a su versión anterior.</p>
<p><span style="font-family: courier new,courier;">$ php -v</span></p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">PHP <strong>5.3.2-1ubuntu4.2</strong> with Suhosin-Patch (cli) (built: May 13 2010 20:03:45)<br />
Copyright (c) 1997-2009 The PHP Group<br />
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies</span></p>
<h2>Degradar PHP.</h2>
<p>Tomar nota de los paquetes relacionados con PHP que se encuentran actualmente instalados.</p>
<p><span style="font-family: courier new,courier;">$ php_installed=`dpkg -l | grep  php| awk  &#8216;{print $2}&#8217; |tr &#8220;\n&#8221; &#8221; &#8220;`</span></p>
<p>Descargar el <em>script</em> de KAndy de la siguiente ubicación y almacenarlo con el nombre de <a href="http://blog.jorgeivanmeza.com/wp-content/uploads/2010/07/downgradePHP.txt" ><span style="font-family: courier new,courier;">downgradePHP.sh</span></a>.</p>
<p style="padding-left: 30px;"><a href="http://mrkandy.wordpress.com/2010/04/16/install-php-5-2-x-in-ubuntu-10-04-lucid/" >http://mrkandy.wordpress.com/2010/04/16/install-php-5-2-x-in-ubuntu-10-04-lucid/</a></p>
<p>Ejecute el <em>script</em> en la máquina que se desea degradar.</p>
<p><span style="font-family: courier new,courier;">$ chmod +x downgradePHP.sh</span></p>
<p><span style="font-family: courier new,courier;">$ ./downgradePHP.sh</span></p>
<p>Recuperar los demás paquetes instalados.</p>
<p><span style="font-family: courier new,courier;">$ sudo apt-get install $php_installed</span></p>
<h2>Verificar la nueva versión de PHP.</h2>
<p><span style="font-family: courier new,courier;">$ php -v</span></p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">PHP <strong>5.2.10-2ubuntu6</strong> with Suhosin-Patch 0.9.7 (cli) (built: Oct 23 2009 16:28:03)<br />
Copyright (c) 1997-2009 The PHP Group<br />
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies</span></p>
<h2>Enlaces.</h2>
<ul>
<li>Install (downgrade) php 5.2.x in Ubuntu 10.04 Lucid.<br />
<a href="http://mrkandy.wordpress.com/2010/04/16/install-php-5-2-x-in-ubuntu-10-04-lucid/" >http://mrkandy.wordpress.com/2010/04/16/install-php-5-2-x-in-ubuntu-10-04-lucid/</a></li>
<li>Ubuntu 10.04 and Drupal.<br />
<a href="http://civicactions.com/blog/2010/may/26/ubuntu_1004_and_drupal" >http://civicactions.com/blog/2010/may/26/ubuntu_1004_and_drupal</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2010/07/degradar-php-5-3-a-5-2-en-gnulinux-ubuntu-10-04/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integración de una autenticación externa con los foros de Simple Machines 1.1.11</title>
		<link>http://blog.jorgeivanmeza.com/2010/05/integracion-de-una-autenticacion-externa-con-los-foros-de-simple-machines-1-1-11/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=integracion-de-una-autenticacion-externa-con-los-foros-de-simple-machines-1-1-11</link>
		<comments>http://blog.jorgeivanmeza.com/2010/05/integracion-de-una-autenticacion-externa-con-los-foros-de-simple-machines-1-1-11/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=integracion-de-una-autenticacion-externa-con-los-foros-de-simple-machines-1-1-11#comments</comments>
		<pubDate>Mon, 10 May 2010 20:59:12 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[autenticacion]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[Foros]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[Integración]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2429</guid>
		<description><![CDATA[Introducción. La situación es la siguiente, se cuenta con un CMS desarrollado en PHP bajo el framework de CodeIgniter con su propio sistema de autenticación en el que se almacenan los usuarios de la siguiente manera. CREATE TABLE IF NOT EXISTS `core_usuario` ( `id_usuario` int(11) unsigned NOT NULL auto_increment, `estado` enum(&#8216;activo&#8217;,'inactivo&#8217;) NOT NULL, `_username` varbinary(16) [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>La situación es la siguiente, se cuenta con un CMS desarrollado en <a href="http://php.net/" >PHP</a> bajo el <em>framework</em> de <a href="http://codeigniter.com/" >CodeIgniter</a> con su propio sistema de autenticación en el que se almacenan los usuarios de la siguiente manera.</p>
<p><span style="font-family: courier new,courier;">CREATE TABLE IF NOT EXISTS `<strong>core_usuario</strong>` (<br />
<strong> `id_usuario` int(11) unsigned NOT NULL auto_increment,</strong><br />
<strong>`estado` enum(&#8216;activo&#8217;,'inactivo&#8217;) NOT NULL,<br />
</strong><strong> `_username` varbinary(16) NOT NULL,<br />
`_password` varbinary(32) NOT NULL,<br />
`nombres` varchar(50) NOT NULL,<br />
`apellidos` varchar(50) NOT NULL,<br />
</strong>`fecha_nacimiento` date default NULL,<br />
`tipo_documento` enum(&#8216;cc&#8217;,'ce&#8217;,'ti&#8217;,'nit&#8217;) NOT NULL,<br />
`documento_identidad` varchar(12) NOT NULL,<br />
`genero` enum(&#8216;m&#8217;,'f&#8217;) NOT NULL,<br />
`correo` varchar(255) NOT NULL,<br />
`pagina` varchar(255) default NULL,<br />
`observaciones` varchar(255) default NULL,<br />
`fecha_creacion` datetime NOT NULL,<br />
`fecha_actualizacion` datetime NOT NULL,<br />
PRIMARY KEY  (`id_usuario`),<br />
);</span></p>
<p>En el sitio se ha instalado un foro basado en la versión 1.1.11 de <a href="http://www.simplemachines.org/" >Simple Machines</a> el cual comparte la base de datos con el CMS.  Se necesita encontrar la forma de unificar los nombres de los usuarios y las contraseñas para tener una única identificación para la autenticación en los dos sistemas.</p>
<p>Para hacer esto se utiliza el API de <a href="http://docs.simplemachines.org/index.php?topic=400.0" >SSI</a> de SMF de la siguiente manera.</p>
<h2>Hooks de integración.</h2>
<p>SMF provee una facilidad para alterar el ciclo de flujo del software mediante la manipulación de <em>hooks</em> que se agregan a etapas específicas del programa para modificar su comportamiento por defecto.  En este caso nos interesa crear un <em>hook</em> sobre el punto <a href="http://www.simplemachines.org/community/index.php?topic=173483.msg1106028#msg1106028" ><span style="font-family: courier new,courier;">integrate_validate_login</span></a> ya que ese es el punto exacto en que SMF va a realizar la validación de los usuarios durante su autenticación.</p>
<p>Para implementar esto se crea un archivo llamado <span style="font-family: courier new,courier;">jimhook.php</span> (el nombre es arbitrario) con el siguiente contenido inicial.</p>
<pre class="php">&lt;?php
define('SMF_INTEGRATION_SETTINGS', serialize(array(
    'integrate_validate_login' =&gt; 'user_validate',
)));

require_once('SSI.php');

function user_validate()
{
    // Implementación de la lógica de la nueva autenticación.
}
?&gt;</pre>
<p>Estos <em>hooks</em> deben asociarse al sistema de foros agregando la siguiente línea al inicio del archivo <span style="font-family: courier new,courier;">index.php</span>.</p>
<pre class="php">include_once("jimhook.php");</pre>
<h2>Conexión a la base de datos.</h2>
<p>Como se mencionó inicialmente el CMS fue desarrollado en CodeIngniter y en este caso, comparte la base de datos con los foros.  El primer paso es obtener la información de conexión a la base de datos desde los archivos de configuración del CMS.</p>
<pre class="php">define('BASEPATH', 1);
include('../pt/system/application/config/database.php');</pre>
<p>Teniendo esta información se realiza una conexión global a la base de datos utilizando las funciones de PDO.</p>
<pre class="php">$pdo = null;

try
{
    $pdo = new PDO("mysql:host={$db['default']['hostname']};dbname={$db['default']['database']}",
                   $db['default']['username'],
                   $db['default']['password'],
                   array(PDO::MYSQL_ATTR_INIT_COMMAND =&gt; "SET NAMES utf8")
    );
}
catch (PDOException $e)
{
    print "Error!: " . $e -&gt; getMessage() . "&lt;br/&gt;";
    die();
}</pre>
<h2>Funciones de apoyo del CMS.</h2>
<p>Se crean algunas funciones básicas que servirán de soporte para el nuevo procedimiento de autenticación.</p>
<pre class="php">function existeUsuarioEnPlataforma($usuario)
{
    global $pdo;

    $stmt = $pdo -&gt; prepare("SELECT id_usuario FROM `usuarios` WHERE user=?");

    $results = $stmt -&gt; execute(array($usuario));

    return ($stmt -&gt; rowCount() &gt; 0);
}</pre>
<p>Verifica si el usuario identificado por el nombre de usuario (<span style="font-family: courier new,courier;">$usuario</span>) existe o no registrado en el CMS.  Retorna <span style="font-family: courier new,courier;">true</span> o <span style="font-family: courier new,courier;">false</span> según se encuentren o no efectivamente registrados.</p>
<pre class="php">function autenticarUsuarioEnPlataforma($usuario, $contrasena)
{
    global $pdo;

    $stmt = $pdo -&gt; prepare("SELECT id_usuario FROM `usuarios` WHERE user=? AND pass=?");

    $results = $stmt -&gt; execute(array($usuario, MD5($contrasena)));

    return ($stmt -&gt; rowCount() &gt; 0);
}</pre>
<p>Verifica que el usuario identificado con el nombre de usuario (<span style="font-family: courier new,courier;">$usuario</span>) tenga efectivamente a <span style="font-family: courier new,courier;">$contraseña</span> como clave de usuario.  Retorna <span style="font-family: courier new,courier;">true</span> en caso de coincidir, <span style="font-family: courier new,courier;">false</span> de lo contrario.</p>
<p>Nótese como el CMS almacena sus contraseñas en <a href="http://co.php.net/md5" >MD5</a> motivo por el cual es necesario realizar esta conversión antes de realizar la comparación en la consulta SQL.</p>
<h2>Funciones de apoyo de los foros.</h2>
<p>De manera análoga, estas funciones facilitan la manipulación de la información en las tablas del sistema de foros, las cuales tienen configurado el prefijo <span style="font-family: courier new,courier;">foros_</span> en sus tablas.</p>
<pre class="php">function existeUsuarioEnForos($usuario)
{
    global $pdo;

    $stmt = $pdo -&gt; prepare("SELECT ID_MEMBER FROM foros_members WHERE memberName = ?");

    $results = $stmt -&gt; execute(array($usuario));

    if($stmt -&gt; rowCount() == 0)
        return false;

    $fuente = $stmt -&gt; fetch();

    return $fuente['ID_MEMBER'];
}</pre>
<p>Verifica si el usuario identificado por el nombre de usuario (<span style="font-family: courier new,courier;">$usuario</span>) existe o no registrado en el foro .  Retorna el identificador del usuario si existe o <span style="font-family: courier new,courier;">false</span> de lo contrario.</p>
<pre class="php">function traerUsuario($usuario, $contrasena)
{
    global $pdo, $sourcedir, $modSettings;

    if(!existeUsuarioEnPlataforma($usuario))
        return false;

    $stmt = $pdo -&gt; prepare("SELECT * FROM `usuarios` WHERE user=?");

    $results = $stmt -&gt; execute(array($usuario));

    $fuente = $stmt -&gt; fetch();

    require_once($sourcedir . '/Subs-Members.php');

    $regOptions = array('username' =&gt; $fuente['user'],
                        'password' =&gt; $contrasena,
                        'password_check' =&gt; $contrasena,
                        'email' =&gt; $fuente['email'],
                        'posts' =&gt; '0',
                        'ID_GROUP' =&gt; '0',
                        'ID_POST_GROUP' =&gt; '4');

    $memberID = registerMember($regOptions);

    return ($memberID &gt; 0);
}</pre>
<p>Obtiene la información del usuario de plataforma identificado por <span style="font-family: courier new,courier;">$usuario</span> y <span style="font-family: courier new,courier;">$contrasena</span>, y lo agrega en la base de datos del foro a través de su API interno.  A este nivel no se realiza ninguna verificación de autenticación.</p>
<pre class="php">function activarUsuarioForo($usuario, $estado='1')
{
    global $pdo;

    $stmt = $pdo -&gt; prepare("UPDATE foros_members SET is_activated = ? WHERE memberName = ?");

    $control = $stmt -&gt; execute(array($estado, $usuario));

    return $control;
}</pre>
<p>Activa al usuario del foro recién creado, el cual por defecto siempre queda en espera de confirmación (<span style="font-family: courier new,courier;">is_activated = 3</span>).</p>
<pre class="php">function actualizarContrasenaForo($usuario, $contrasena)
{
    global $pdo;

    $passwd       = sha1(strtolower($usuario) . $contrasena);
    $passwordSalt = substr(md5(mt_rand()), 0, 4);

    $stmt = $pdo -&gt; prepare("UPDATE foros_members SET passwd = ?, passwordSalt = ? WHERE memberName = ?");

    $control = $stmt -&gt; execute(array($passwd, $passwordSalt, $usuario));

    return $control;
}</pre>
<p>Actualiza la <span style="font-family: courier new,courier;">$contrasena</span> del <span style="font-family: courier new,courier;">$usuario</span> en el sistema de foros.  Nótese como la <span style="font-family: courier new,courier;">$contrasena</span> se recibe de manera plana y se almacena en la base de datos de SMF en <a href="http://co.php.net/sha1" >SHA1</a>.</p>
<h2>Acerca del comportamiento del <em>login</em> de SMF.</h2>
<p>Algo que se debe tener en cuenta acerca del comportamiento del <em>login </em>de SMF es que desde el cliente (navegador del usuario) se envía la contraseña ya en su propia representación SHA1 así que si la contraseña con que se va a comparar no está en la misma representación, como en este caso, el CMS la almacena en MD5, se tiene entonces un problema.</p>
<p>Para solventar esto, el sistema de foros permite solicitar nuevamente la contraseña al usuario (<em>retry</em>) y en este segundo intento la envía totalmente plana para su manipulación libre.  En este punto es donde la aprovechamos para verificar la autenticación del usuario contra la información del CMS, crear el usuario en el foro si no existe y actualizar la contraseña en el foro previniendo que haya sido actualizada antes en el CMS.</p>
<h2>Implementación del nuevo proceso de autenticación.</h2>
<pre class="php">function user_validate()
{
    $user = $_REQUEST['user'];
    $id   = 0;

    // Verificar un usuario proveniente de plataforma.

    if(existeUsuarioEnPlataforma($user))
    {
        $id = existeUsuarioEnForos($user);

        // Nueva lógica de autenticación.
    }

    // El usuario no existe en plataforma, verificar los nativos del foro.

    return false;
}</pre>
<p>La base de la nueva autenticación es entonces la definición de la función <span style="font-family: courier new,courier;">user_validate</span> que corresponde con la especificada inicialmente durante la configuración de los <em>hooks</em>.</p>
<p>En ella se verifica inicialmente si el usuario que intenta acceder al sistema (<em>login</em>) se encuentra presente o no en la base de datos de usuarios del CMS.  En caso de no estar presente el control de la autenticación se libera para que el sistema verifique sus usuarios propios, esto permite definir también usuarios internos del foro que no estén presentes en el CMS.</p>
<p>El paso siguiente consiste en determinar si el usuario existe previamente o no en el foro, es decir, no es su primer ingreso al mismo.  A partir de esta respuesta se toma uno de los siguientes caminos.</p>
<ul>
<li>Si no está disponible la contraseña plana (primer <em>login</em>) se solicita nuevamente (segundo <em>login</em>).</li>
<li>Si el usuario no existe en el foro entonces ...
<ul>
<li>Se verifica que el nombre de usuario y la contraseña coincidan.</li>
<li>Se crea el usuario en el foro.</li>
<li>Se activa al nuevo usuario.</li>
</ul>
</li>
<li>Si el usuario ya existía previamente en el foro entonces ...
<ul>
<li>Se verifica que el nombre de usuario y la contraseña coincidan.</li>
<li>Se actualiza la contraseña en el foro por si ha sido actualizada previamente en el CMS.</li>
</ul>
</li>
</ul>
<p>La implementación de estas acciones se detalla a continuación.  En el caso en que el usuario no exista previamente en el foro se ejecuta la siguiente lógica del negocio.</p>
<pre class="php">if($id === false)
{
    // Esta disponible la contrasena (2do. login).

    if(isset($_REQUEST['passwrd']) &amp;&amp; !empty($_REQUEST['passwrd']))
    {
        $auth = autenticarUsuarioEnPlataforma($user, $_REQUEST['passwrd']);

        if($auth)                           // La informacion del usuario es valida.
        {
            $id = traerUsuario($user, $_REQUEST['passwrd']);

            activarUsuarioForo($user);

            return false;                   // La autenticacion tiene EXITO.
        }
        else                                // La informacion del usuario NO es valida.
            return true;                    // La autenticacion FALLA.
    }
    else                                    // No esta disponible la contrasena (1er. login).
        return "retry";                     // Vuelva a solicitar el login para confirmar.
}</pre>
<p>En el caso en que el usuario si exista previamente en el foro, el procedimiento es mas simple y se ejecuta  la siguiente lógica del negocio.</p>
<pre class="php">// El usuario existe en el foro.

if($id !== false)
{
    // Esta disponible la contrasena (2do. login) -&gt; actualizar la contraseña en el foro.

    if(isset($_REQUEST['passwrd']) &amp;&amp; !empty($_REQUEST['passwrd']))
    {
        $auth = autenticarUsuarioEnPlataforma($user, $_REQUEST['passwrd']);

        if($auth)                           // La informacion del usuario es valida.
        {
            actualizarContrasenaForo($user, $_REQUEST['passwrd']);

            return false;                   // La autenticacion tiene EXITO.
        }
        else                                // La informacion del usuario NO es valida.
            return true;                    // La autenticacion FALLA.
    }
    else                                    // No esta disponible la contrasena (1er. login).
        return "retry";                     // Vuelva a solicitar el login para confirmar.
}</pre>
<h2>Conclusiones.</h2>
<p>Hasta ahora, con poca experiencia en su uso, SMF parece ser un sistema de foros útil y práctico.  El proceso de determinar esta unificación de la autenticación fue largo y doloroso debido a la poca documentación que pude encontrar acerca del API, la cual en su mayor parte se encuentra diseminada en los foros de su sitio web.</p>
<p>En términos de su código parece tener un nivel decente de flexibilidad, el concepto de <em>hooks</em> permite realizar modificaciones interesantes al flujo normal del software, sin embargo es difícil formalizarlo al no contar con información suficiente de su lógica de funcionamiento.  Algunas partes del software, en especial los temas, adolecen de separación MVC por lo que se hace necesario editar funciones, entre comillas, que retornan el código HTML que se desea modificar siendo esto molesto, difícil y propenso a errores, sobretodo si se compara con tener archivos PHP separados con la lógica y HTML con la presentación como sería una mejor opción.</p>
<p>Finalmente, después de varios días de luchas y de pruebas, la unificación de la autenticación está funcionando y se ve bien, de todas maneras es mi primer acercamiento a este software por lo que no puedo garantizar que sea la mejor aproximación.  Como siempre, estoy abierto a sugerencias constructivas.</p>
<h2>Enlaces.</h2>
<ul>
<li>Simple Machines.<br />
<a href="http://www.simplemachines.org/" >http://www.simplemachines.org/</a>
<ul>
<li>A guide to the SMF integration hooks.<br />
<a href="http://www.simplemachines.org/community/index.php?topic=173483.0" >http://www.simplemachines.org/community/index.php?topic=173483.0</a></li>
</ul>
</li>
<li>CodeIgniter.<br />
<a href="http://codeigniter.com/" >http://codeigniter.com/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2010/05/integracion-de-una-autenticacion-externa-con-los-foros-de-simple-machines-1-1-11/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Los controladores en Yii</title>
		<link>http://blog.jorgeivanmeza.com/2010/01/los-controladores-en-yii-2/</link>
		<comments>http://blog.jorgeivanmeza.com/2010/01/los-controladores-en-yii-2/#comments</comments>
		<pubDate>Sat, 02 Jan 2010 05:45:56 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[yii]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2262</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>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.</p>
<p>Su clase base es <span style="font-family: courier new,courier;">CController</span> y en ellos se implementan <strong>Acciones</strong> (definen la lógica de la aplicación) y <strong>Filtros</strong> (establecen validaciones o controles antes y después de la ejecución de las acciones).</p>
<p>El usuario invoca indirectamente a los controladores especificando un <strong>ruta</strong> a través del controlador frontal o <span style="font-family: courier new,courier;">Application</span>.</p>
<h2>La ruta del requerimiento.</h2>
<p>El URL solicitado determina que controlador y que acción se van a ejecutar para resolver el requerimiento del usuario.</p>
<p>Los URL tienen el siguiente formato.</p>
<p style="padding-left: 30px;">Sin <em>URL limpias</em> (por defecto).</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">http://servidor/index.php?r=ControladorId/AcciónId</span></p>
<p style="padding-left: 30px;">Con <em>URL limpias</em>.</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">http://servidor/ControladorId/AcciónId</span></p>
<p style="padding-left: 30px;">Si se utilizan módulos (y <em>URL limpias</em> para este ejemplo).</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">http://servidor/MóduloId/ControladorId/AcciónId</span></p>
<ul>
<li>El archivo fuente del controlador se ubica en <span style="font-family: courier new,courier;">protected/controllers/<strong>ControladorId</strong>Controller.php</span>.</li>
<li>El nombre de la clase allí contenida deberá ser <span style="font-family: courier new,courier;"><strong>ControladorId</strong>Controller</span>.</li>
<li>Se invoca a la acción (ver mas adelante) <span style="font-family: courier new,courier;">AcciónId</span>.  En caso de no haberse especificado una se considera la acción por defecto del controlador, comúnmente <span style="font-family: courier new,courier;">index</span>.</li>
</ul>
<h2>Las acciones.</h2>
<p>Pueden implementarse de dos maneras.</p>
<ul>
<li>Como métodos del mismo controlador.</li>
<li>Como clases que heredan de <span style="font-family: courier new,courier;">CAction</span>.</li>
</ul>
<h3>Acciones implementadas como métodos del controlador.</h3>
<ul>
<li>El nombre del método deberá ser <span style="font-family: courier new,courier;">action<strong>AcciónId</strong></span>.</li>
</ul>
<p>En el siguiente ejemplo se muestra al controlador <span style="font-family: courier new,courier;">User</span> que implementa la acción <span style="font-family: courier new,courier;">add</span> como un método suyo.</p>
<pre class="php">class UserController extends CController
{
    public function actionAdd()
    {
        // Implementación ...
    }
}</pre>
<h3>Acciones implementadas como clases independientes.</h3>
<ul>
<li>Los objetos acción heredan de <span style="font-family: courier new,courier;">CAction</span>.</li>
<li>El nombre de la clase es <span style="font-family: courier new,courier;"><strong>AcciónId</strong>Action</span> (por convención, no es obligatorio).</li>
<li>Se almacena en un archivo bajo la ruta <span style="font-family: courier new,courier;">protected/controllers/<strong>controladorId</strong>/<strong>AcciónId</strong>Action.php.</span></li>
<li>Su ubicación puede referenciarse mediante alias de esta manera: <span style="font-family: courier new,courier;">application.controllers.<strong>controladorId</strong>.<strong>AcciónId</strong>Action</span>.</li>
<li>Es obligatorio sobreescribir el método <span style="font-family: courier new,courier;">run()</span> de la acción para definir allí su implementación.</li>
</ul>
<p>En el siguiente código se muestra la acción <span style="font-family: courier new,courier;">remove</span> del controlador <span style="font-family: courier new,courier;">User</span> implementada como una clase independiente.</p>
<pre class="php">class RemoveAction extends CAction
{
    public function run()
    {
        // Implementación ...
    }
}</pre>
<p>Esta clase se almacena entonces en el archivo <span style="font-family: courier new,courier;">protected/controllers/user/RemoveAction.php</span>.</p>
<p>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 <span style="font-family: courier new,courier;">actions</span> del controlador de la siguiente manera.</p>
<pre class="php">class UserController extends CController
{
   public function actions()
   {
       return array(
           'remove' =&gt; 'application.controllers.user.RemoveAction'
       );
   }
}</pre>
<h2>Los filtros.</h2>
<ul>
<li>Permiten realizar verificaciones y validaciones antes y después de la ejecución de las acciones.</li>
<li>Una acción puede tener asociados múltiples filtros.</li>
<li>Los filtros se ejecutan en el orden en que fueron especificados.</li>
<li>Un filtro puede abortar la ejecución de los demás filtros y de la acción misma.</li>
<li>De manera análoga a las acciones, los filtros pueden implementarse de dos maneras también.
<ul>
<li>Como métodos del mismo controlador.</li>
<li>Como clases que heredan de <span style="font-family: courier new,courier;">CFilter</span>.</li>
</ul>
</li>
</ul>
<h3>Filtros implementados como métodos del controlador.</h3>
<ul>
<li>El nombre del método debe empezar por la palabra <span style="font-family: courier new,courier;">filter</span>.</li>
<li>Deberá recibir como parámetro a <span style="font-family: courier new,courier;">$filterChain</span>.</li>
</ul>
<p>En el siguiente ejemplo se muestra al controlador <span style="font-family: courier new,courier;">User</span> que implementa al filtro <span style="font-family: courier new,courier;">checkUser</span> como un método suyo.</p>
<pre class='php'>class UserController extends CController
{
    public function filterCheckUser($filterChain)
    {
        // Implementación ... invocar $filterChain -&gt; run()
        // para continuar con el próximo filtro
    }
}</pre>
<h3>Filtros implementados como clases independientes.</h3>
<ul>
<li>Los objetos acción heredan de <span style="font-family: courier new,courier;">CFilter</span>.</li>
<li>El nombre de la clase es <span style="font-family: courier new,courier;"><strong>FiltroId</strong>Filter</span> (por convención, no es obligatorio).</li>
<li>Se almacena en un archivo bajo la ruta <span style="font-family: courier new,courier;">protected/filters/<strong>FiltroId</strong>Filter.php</span>.</li>
<li>Su ubicación puede referenciarse mediante alias de esta manera: <span style="font-family: courier new,courier;">application.filters.<strong>FiltroId</strong>Filter</span>.</li>
<li>Es obligatorio sobreescribir los métodos <span style="font-family: courier new,courier;">preFilter($filterChain)</span> y <span style="font-family: courier new,courier;">postFilter($filterChain)</span> del filtro para definir que hacer antes y después de ejecutar la acción.</li>
</ul>
<p>En el siguiente código se muestra al filtro <span style="font-family: courier new,courier;">isValid</span> del controlador <span style="font-family: courier new,courier;">User</span> implementado como una clase independiente.</p>
<pre class='php'>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.
    }
}</pre>
<p>Esta clase se almacena entonces en el archivo <span style="font-family: courier new,courier;">protected/filters/IsValidFilter.php</span>.</p>
<p>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 <span style="font-family: courier new,courier;">filters</span> del controlador de la siguiente manera.</p>
<pre class='php'>class UserController extends CController
{
   public function filters()
   {
       return array(
           'checkUser + add, remove',

           array(
               'application.filters.IsValidFilter - add, remove',
               'admin' =&gt; false
           )
       );
   }
}</pre>
<ul>
<li><span style="font-family: courier new,courier;">checkUser</span> es un filtro basado en un método del controlador.</li>
<li><span style="font-family: courier new,courier;">isValid</span> es un filtro basado en una clase externa.</li>
<li>Es posible especificar los filtros con una notación de arreglo para determinar valores específicos para los atributos del filtro.</li>
</ul>
<p>Los operadores <span style="font-family: courier new,courier;">+</span> y <span style="font-family: courier new,courier;">-</span> actúan como determinadores del alcance de los filtros sobre las acciones especificadas de la siguiente manera.</p>
<ul>
<li><span style="font-family: courier new,courier;">+</span> determina exactamente a cuales acciones se les debe aplicar el filtro.  De esta manera, el filtro <span style="font-family: courier new,courier;">checkUser</span> se aplicará a las acciones <span style="font-family: courier new,courier;">add</span> y <span style="font-family: courier new,courier;">remove</span> únicamente.</li>
<li><span style="font-family: courier new,courier;">-</span> determina a cuales acciones NO se les debe aplicar el filtro.  Así, el filtro <span style="font-family: courier new,courier;">isValid</span> se aplicará a todas las acciones EXCEPTO a <span style="font-family: courier new,courier;">add</span> y <span style="font-family: courier new,courier;">remove</span>.</li>
<li>Si no se especifica ninguno de los dos modificadores, el filtro aplicará a todas las acciones del controlador.</li>
</ul>
<h2>Enlaces.</h2>
<ul>
<li>Yii Documentation: controllers.<br />
<a href="http://www.yiiframework.com/doc/guide/basics.controller" >http://www.yiiframework.com/doc/guide/basics.controller</a></li>
<li>Yii PHP Framwork.<br />
<a href="http://www.yiiframework.com/" >http://www.yiiframework.com/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2010/01/los-controladores-en-yii-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ejemplo rápido y simple de AJAX con PHP y PrototypeJS</title>
		<link>http://blog.jorgeivanmeza.com/2009/11/ejemplo-rapido-y-simple-de-ajax-con-php-y-prototypejs/</link>
		<comments>http://blog.jorgeivanmeza.com/2009/11/ejemplo-rapido-y-simple-de-ajax-con-php-y-prototypejs/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 17:33:24 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Desarrollo de hardware]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2148</guid>
		<description><![CDATA[Introducción.
Intentando recuperar mis neuronas que saben de Prototype para continuar por fin con uno de los proyectos que se encontraba en pausa permanente, el día de hoy me día a la breve tarea de recordar un poco la invocación asíncrona y la manipulación del DOM utilizando esta librería.  Para hacer una pequeña práctica decidí modificar [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>Intentando recuperar mis neuronas que saben de <a href="http://prototypejs.org/" >Prototype</a> para continuar por fin con uno de los proyectos que se encontraba en pausa permanente, el día de hoy me día a la breve tarea de recordar un poco la invocación asíncrona y la manipulación del DOM utilizando esta librería.  Para hacer una pequeña práctica decidí modificar el ejemplo de la <a href="http://blog.jorgeivanmeza.com/2009/10/ejemplo-de-ajax-rapido-y-simple-con-php-y-jquery/" >calculadora que se basaba en jQuery y PHP</a> para migrar su código de acuerdo con la especificación de Prototype.</p>
<p>Las modificaciones necesarias se centraron en la inclusión de la librería javascript en la página web (<em>frontend</em>) y en reescribir la invocación asíncrona de la aplicación web en PHP (<em>backend</em>).</p>
<h2>Procedimiento.</h2>
<p>Reemplazar la inclusión de la librería de jQuery por la de Prototype.  Para este caso se continúo utilizando el API de Google AJAX.</p>
<pre class="javascript">&lt;script src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
&lt;script&gt;google.load("prototype", "1.6");&lt;/script&gt;</pre>
<p>Posteriormente se asoció el manejo del evento de presión del botón <span style="font-family: courier new,courier;">igual</span> a la invocación de la función <span style="font-family: courier new,courier;">procesar</span>, esto se realiza tan pronto como la estructura de la página (código HTML) se encuentra cargada completamente por el navegador.</p>
<pre class="javascript">/* Código a ejecutarse tan pronto como la
   página ha sido cargada por el navegador */

document.observe('dom:loaded', function()
{
    /* Asociar el evento de clic del botón 'igual'
       con la lógica del negocio de la aplicación */

    Event.observe('igual', 'click', procesar);
});</pre>
<p>Finalmente se implementa la función <span style="font-family: courier new,courier;">procesar</span> que realizará la invocación asíncrona del cálculo matemático.  Esta función consta de las siguientes partes.</p>
<ol>
<li>Información básica del requerimiento.</li>
<li>Que hacer en caso de éxito.</li>
<li>Que hacer en caso de fracaso.</li>
</ol>
<p>El requerimiento incluye la siguiente información básica de conexión.</p>
<ul>
<li>El URL de la aplicación remota a invocar (<em>backend</em>).</li>
<li>El método HTTP a utilizar.</li>
<li>Los parámetros de la página web a enviarse.</li>
</ul>
<pre class="javascript">function procesar()
{
    new Ajax.Request('calcular.php',                                         /* URL a invocar asíncronamente */
    {
        method:       'post',                                                /* Método utilizado para el requerimiento */
        parameters:   $('formulario').serialize(true),                       /* Información local a enviarse con el requerimiento */</pre>
<p>En caso de que la invocación asíncrona tenga un resultado exitoso se deberán realizar los siguientes pasos.</p>
<ul>
<li>Mostrar un mensaje de éxito en color verde.</li>
<li>Desplegar el valor del resultado obtenido en el campo definido para tal fin.</li>
</ul>
<pre class="javascript">        /* Que hacer en caso de ser exitoso el requerimiento */

        onSuccess: function(transport)
        {
            /* Cambiar el color del texto a verde */

            $('mensaje').setStyle('color: #0ab53a');

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

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

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

            $('resultado').update(transport.responseText);
        },</pre>
<p>En caso de que fracase el proceso de invocación asíncrona se deberán realizar los siguientes pasos análogos.</p>
<ul>
<li>Mostrar el mensaje de error proveniente del servidor, en color rojo.</li>
<li>Limpiar cualquier resultado previo para evitar confusiones con la operación.</li>
</ul>
<pre class="javascript">        /* Que hacer en caso de que sea fallido el requerimiento */

        onFailure: function(transport)
        {
            /* Cambiar el color del texto a rojo */

            $('mensaje').setStyle('color: #ff0e0e');

            /* Mostrar el mensaje de error */

            $('mensaje').update('Error: ' + transport.responseText);

            /* Limpiar cualquier resultado anterior */

            $('resultado').update('Error');
        }
    });
}</pre>
<h2>Enlaces.</h2>
<ul>
<li>Demostración &amp; descarga del código fuente.<br />
<a href="http://demo.jorgeivanmeza.com/Prototype/AjaxSimpleRapido-Calc/" >http://demo.jorgeivanmeza.com/Prototype/AjaxSimpleRapido-Calc/</a></li>
<li>Prototype Javascript Framework.<br />
<a href="http://prototypejs.org/" >http://prototypejs.org/</a></li>
<li>Prototype Introduction to Ajax.<br />
<a href="http://www.prototypejs.org/learn/introduction-to-ajax" >http://www.prototypejs.org/learn/introduction-to-ajax</a></li>
<li>Prototype's AJAX Request API.<br />
<a href="http://api.prototypejs.org/ajax/ajax/request.html" >http://api.prototypejs.org/ajax/ajax/request.html</a></li>
<li>Prototype's Element API.<br />
<a href="http://api.prototypejs.org/dom/element.html" >http://api.prototypejs.org/dom/element.html</a></li>
<li>Ejemplo de AJAX rápido y simple con PHP y jQuery.<br />
<a href="http://blog.jorgeivanmeza.com/2009/10/ejemplo-de-ajax-rapido-y-simple-con-php-y-jquery/" >http://blog.jorgeivanmeza.com/2009/10/ejemplo-de-ajax-rapido-y-simple-con-php-y-jquery/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/11/ejemplo-rapido-y-simple-de-ajax-con-php-y-prototypejs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ejemplo de AJAX rápido y simple con PHP y jQuery</title>
		<link>http://blog.jorgeivanmeza.com/2009/10/ejemplo-de-ajax-rapido-y-simple-con-php-y-jquery/</link>
		<comments>http://blog.jorgeivanmeza.com/2009/10/ejemplo-de-ajax-rapido-y-simple-con-php-y-jquery/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 04:54:32 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2069</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>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 <em>framework</em> de jQuery.</p>
<p>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 <a href="http://es.wikipedia.org/wiki/XMLHttpRequest" ><span style="font-family: courier new,courier;">XMLHTTPRequest</span></a>) no la realizaremos directamente sino que utilizaremos el <em>framework</em> 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.</p>
<h2>Qué es AJAX ?</h2>
<p>AJAX es el acrónimo de <em>Asynchronous JavaScript and XML</em>, 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 (<a href="http://en.wikipedia.org/wiki/Postback" ><em>postback</em></a>) la página web por completo.</p>
<p>Su implementación se basa en el objeto <a href="http://en.wikipedia.org/wiki/XMLHttpRequest" >XMLHttpRequest</a> 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.</p>
<p>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 <a href="http://www.gmail.com/" >GMail</a>) y las aplicaciones geográficas (como <a href="http://maps.google.com/" >Google Maps</a>).  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.</p>
<p>Consulte mas información acerca de <a href="http://en.wikipedia.org/wiki/AJAX" >AJAX en Wikipedia</a>.</p>
<h2>Procedimiento.</h2>
<p>Estos son los pasos generales que realizaremos para implementar nuestra pequeña aplicación.</p>
<ol>
<li>Crear la estructura básica de la página web.</li>
<li>Implementar el formulario de la calculadora.</li>
<li>Mejorar la presentación del formulario.</li>
<li>Implementar la lógica del negocio de la calculadora.</li>
<li>Incluír una referencia a la librería de jQuery en la página web.</li>
<li>Implementar los llamados asíncronos a la lógica del negocio de la calculadora.</li>
</ol>
<h2>La estructura básica de la página.</h2>
<p>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 <em>bloc de notas</em> hasta otro mas elaborado como <em>Dreamweaver</em> o <em>Eclipse PDT</em>.  Lo importante es que sea un editor de archivos planos.  En mi caso estoy probando <a href="http://www.gphpedit.org/" >gPHPEdit</a> para Linux el cual se ve hasta ahora simple y conciso.  Para el caso de Windows un editor simple como el <a href="http://notepad-plus.sourceforge.net/" >Notepad++</a> servirá.</p>
<p>Creamos entonces el archivo <span style="font-family: courier new,courier;">calculadora.html</span> con el siguiente contenido.</p>
<pre class="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
    &lt;head&gt;
       &lt;!-- Documento HTML con carácteres UTF8 --&gt;
       &lt;meta http-equiv="Content-type" content="text/html; charset=utf-8" /&gt;

       &lt;title&gt;Calculadora AJAX&lt;/title&gt;

       &lt;!-- Clases CSS internas --&gt;

       &lt;!-- Referencias a Javascripts externos --&gt;

       &lt;!-- Código Javascript interno --&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;!-- Contenido del documento --&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>He incluído algunos <span style="font-family: courier new,courier;">&lt;!--</span> comentarios <span style="font-family: courier new,courier;">--&gt;</span> 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 <em>XHTML 1.1 transitional</em>.</p>
<h2>El formulario de la calculadora.</h2>
<p>Este deberá contar con las siguientes partes básicas.</p>
<ol>
<li>Una sección para los mensajes de error (<em>mensaje</em>) de la aplicación.</li>
<li>Un <span style="font-family: courier new,courier;">form</span> (<em>formulario</em>) que representa al formulario en HTML.</li>
<li>Un campo de texto (<em>operando1</em>) para 4 dígitos para que el usuario ingrese al primer operando.</li>
<li>Un campo de selección (<em>operador</em>) para que el usuario elija la operación a efectuarse: suma, resta, multiplicación o división.</li>
<li>Un campo de texto (<em>operando2</em>) para 4 dígitos para que el usuario ingrese al segundo operando.</li>
<li>Un botón (<em>igual</em>) para invocar la operación de los datos.</li>
<li>Una sección (<em>resultado</em>) para mostrar el resultado de la operación.</li>
</ol>
<p>La siguiente es la implementación de esta sección y debe insertarse como el <em>Contenido del documento</em> en la plantilla de la estructura básica de la página web.</p>
<pre class="html">&lt;div id='pagina'&gt;
    &lt;div id='mensaje'&gt;&amp;nbsp;&lt;/div&gt;

    &lt;form id='formulario' action='#' method='post'&gt;
        &lt;input type='text' id='operando1' name='operando1' value='' size='4' maxlength='4' /&gt;

        &lt;select id='operador' name='operador'&gt;
            &lt;option value='SU'&gt;+&lt;/option&gt;
            &lt;option value='RE'&gt;-&lt;/option&gt;
            &lt;option value='MU'&gt;*&lt;/option&gt;
            &lt;option value='DI'&gt;/&lt;/option&gt;
        &lt;/select&gt;

        &lt;input type='text' id='operando2' name='operando2' value='' size='4' maxlength='4' /&gt;

        &lt;input type='button' id='igual' value='=' /&gt;

        &lt;span id='resultado'&gt;&amp;nbsp;&lt;/span&gt;
    &lt;/form&gt;
 &lt;/div&gt;</pre>
<div style="border: 1px dotted #ff0000; margin: auto; padding: 5px; width: 90%;"><span style="color: #ff0000;"><strong>Nota</strong></span>.  El atributo del nombre (<span style="font-family: courier new,courier;">name</span>) 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.</div>
<h2>Mejorar la presentación del formulario.</h2>
<p>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.</p>
<div id="attachment_2077" class="wp-caption aligncenter" style="width: 511px"><a href="http://blog.jorgeivanmeza.com/wp-content/uploads/2009/10/screenshot_034.png"><img class="size-full wp-image-2077" title="screenshot_034" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2009/10/screenshot_034.png" alt="Interfaz de usuario de la calculadora" width="501" height="136" /></a><p class="wp-caption-text">Interfaz de usuario de la calculadora</p></div>
<p>Las nuevas características se especifican utilizando hojas de estilo (<a href="http://en.wikipedia.org/wiki/CSS" >CSS</a>) y se referencian a través de sus identificadores, etiquetas o clases.</p>
<p>El siguiente código CSS realiza las modificaciones propuestas al formulario.  Estas se deben insertar en la sección de <em>Clases CSS Internas</em>.</p>
<pre class="css">&lt;style type="text/css"&gt;

 #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 */
 }

 &lt;/style&gt;</pre>
<h2>La lógica del negocio de la calculadora.</h2>
<p>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 <span style="font-family: courier new,courier;">calcular.php</span>.</p>
<p>Los pasos generales que deben realizarse para llevar a cabo exitosamente el cálculo del valor resultante son los siguientes.</p>
<ol>
<li>Obtener la información provista por el usuario: operandos y operador.</li>
<li>Verificar que la información proporcionada por el usuario sea válida.</li>
<li>Realizar la operación indicada con los valores suministrados.</li>
<li>Mostrar el resultado.</li>
</ol>
<p>Como veremos a continuación la implementación de estos pasos es ligeramente mas interesante que su simple mención.</p>
<p>Para iniciar el código PHP, le indicamos al navaegador que la respuesta del <em>script</em> será un texto.  Este paso específico es opcional ya que para PHP este es el tipo de respuesta por defecto.</p>
<pre class="php">&lt;?php

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

header('Content-type: text/html');</pre>
<p>La implementación de las siguientes acciones la vamos a recubrir en un bloque <span style="font-family: courier new,courier;">try</span>/<span style="font-family: courier new,courier;">catch</span> ya que es suceptible de generar errores y consecuentemente, lanzar excepciones.</p>
<p>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 <em>post</em> y los elementos se diferencian por su identificador.</p>
<pre class="php">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}]");</pre>
<p>Realizamos una tarea similar con el operador, obtenemos su valor y verificamos que sea válido.</p>
<pre class="php">    /* 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}]");</pre>
<p>Definimos una variable para almacenar el resultado de la operación solicitada.</p>
<pre class="php">    /* Almacenar resultado, inicialmente desconocido */

    $resultado = 0;</pre>
<p>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.</p>
<pre class="php">    /* 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;
    }
}</pre>
<p>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.</p>
<p>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.</p>
<pre class="php">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 -&gt; getMessage();

    exit(1);
}</pre>
<p>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.</p>
<pre class="php">/* 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);

?&gt;</pre>
<h2>Incluír la referencia a jQuery.</h2>
<p>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.</p>
<p>Para hacer esto se debe agregar la siguiente línea en la sección <em>Referencias de Javascript externos</em>.</p>
<pre class="php">&lt;script src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
&lt;script&gt;google.load("jquery", "1");&lt;/script&gt;</pre>
<p>Este fragmento utiliza <a href="http://code.google.com/apis/ajaxlibs/" >Google AJAX Libraries</a> que nos permite incluír los principales <em>frameworks</em> 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.</p>
<p>Una forma mas tradicional de hacer lo mismo es el descargar por nuestra propia cuenta la distribución de jQuery desde su <a href="http://docs.jquery.com/Downloading_jQuery#Download_jQuery" >sitio web</a>, almacenar el archivo en nuestro servidor y hacer una referencia desde la página web como se muestra a continuación.</p>
<pre class="php">&lt;script src='http://www.servidor.com/ruta/jquery.js' type='text/javascript'&gt;&lt;/script&gt;</pre>
<h2>Implementar las invocaciones asíncronas.</h2>
<p>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 <em>Código Javascript interno</em>.</p>
<p>El primer paso que se debe realizar para su implementación es relacionar el evento de presionar el botón <span style="font-family: courier new,courier;">igual</span> 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 <span style="font-family: courier new,courier;">onClick</span> para el elemento <span style="font-family: courier new,courier;">INPUT</span> 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.</p>
<p>Para hacer esto, tan pronto como se carga la página se asocia el evento de clic sobre el botón de <span style="font-family: courier new,courier;">igual </span>para que se invoque la función <span style="font-family: courier new,courier;">procesar</span>.</p>
<pre class="javascript">&lt;script type='text/javascript'&gt;

/* 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();
	});
});</pre>
<p>El siguiente paso es la implementación de la función <span style="font-family: courier new,courier;">procesar</span>.  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.</p>
<p>Una invocación asíncrona típica incluye la siguiente información básica.</p>
<ol>
<li>El URL de la aplicación web a invocarse.</li>
<li>El tipo del requerimiento a realizarse (<span style="font-family: courier new,courier;">GET</span> o <span style="font-family: courier new,courier;">POST</span> normalmente).</li>
<li>Los datos a enviarse como parámetros desde el formulario web (en formato <a href="http://en.wikipedia.org/wiki/Query_string" ><em>QueryString</em></a>).</li>
<li>Definir la implementación de que hacer si la invocación es exitosa.</li>
<li>Definir la implementación de que hacer si la invocación es fallida.</li>
</ol>
<p>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 <span style="font-family: courier new,courier;">calcular.php</span> mediante el método <span style="font-family: courier new,courier;">post</span> y se le enviarán como parámetros los campos del formulario <span style="font-family: courier new,courier;">formulario</span>.</p>
<pre class="javascript">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 */</pre>
<p>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.</p>
<pre class="javascript">		/* 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);
		},</pre>
<p>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.</p>
<pre class="javascript">		/* 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

&lt;/script&gt;</pre>
<h2>Enlaces.</h2>
<ul>
<li>Demostración &amp; descarga del código fuente.<br />
<a href="http://demo.jorgeivanmeza.com/jQuery/AjaxSimpleRapido-Calc/" >http://demo.jorgeivanmeza.com/jQuery/AjaxSimpleRapido-Calc/</a></li>
<li>jQuery.<br />
<a href="http://jquery.com/" >http://jquery.com/</a></li>
<li>Simplify Ajax development with jQuery<br />
<a href="http://www.ibm.com/developerworks/library/x-ajaxjquery.html" >http://www.ibm.com/developerworks/library/x-ajaxjquery.html</a></li>
</ul>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 1096px; width: 1px; height: 1px;">
<pre class="html">id='operador'</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/10/ejemplo-de-ajax-rapido-y-simple-con-php-y-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Instalación básica de Kohana 3</title>
		<link>http://blog.jorgeivanmeza.com/2009/10/instalacion-basica-de-kohana-3/</link>
		<comments>http://blog.jorgeivanmeza.com/2009/10/instalacion-basica-de-kohana-3/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 05:26:47 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[Kohana]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2038</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p><a href="http://www.kohanaphp.com/" >Kohana</a> es un framework de PHP que siempre me ha parecido interesante por su simplicidad y claridad.  Inicialmente se originó como un <em>fork</em> de <a href="http://codeigniter.com/" >Codeigniter</a> 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).</p>
<p>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.</p>
<p>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.</p>
<p>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 <em>inline</em> del mismo framework, acabo de instalarlo y de activar el módulo respectivo para consultarla.</p>
<p>La idea es instalar el framework (<span style="font-family: courier new,courier;">system/</span> y <span style="font-family: courier new,courier;">modules/</span>) en un directorio por fuera del árbol público (<span style="font-family: courier new,courier;">/home/www/kohana/3.0_dev</span>) y sólo instalar en él lo realmente relacionado con la aplicación (<span style="font-family: courier new,courier;">/home/www/public/kohana/application</span>).</p>
<h2>Procedimiento.</h2>
<p>La versión convencional de este procedimiento inicia descargando la versión .ZIP de la distribución desde el <a href="http://dev.kohanaphp.com/projects/kohana3/files" >repositorio del proyecto</a>, 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.</p>
<h3>Descargar la distribución mas reciente de Kohana 3.</h3>
<p><span style="font-family: courier new,courier;">$ cd /home/www/public<br />
</span></p>
<p><span style="font-family: courier new,courier;">$ git clone git://github.com/kohana/kohana.git</span></p>
<p><span style="font-family: courier new,courier;">$ cd kohana</span></p>
<p><span style="font-family: courier new,courier;">$ git submodule init</span></p>
<p><span style="font-family: courier new,courier;">$ git submodule update</span></p>
<h3>Ubicación del framework en el directorio no público.</h3>
<p><span style="font-family: courier new,courier;">$ mkdir -p /home/www/kohana/3.0_dev</span></p>
<p><span style="font-family: courier new,courier;">$ mv system/ modules/ /home/www/kohana/3.0_dev</span></p>
<h3>Establecer los permisos requeridos para la aplicación.</h3>
<p><span style="font-family: courier new,courier;">$ chmod 777 application/logs/</span></p>
<p><span style="font-family: courier new,courier;">$ chmod 777 application/cache/</span></p>
<h3>Realizar la configuración general.</h3>
<p><span style="font-family: courier new,courier;">$ vi index.php</span></p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">$application = 'application';<br />
$modules     = '/home/www/kohana/3.0_dev/modules';<br />
$system      = '/home/www/kohana/3.0_dev/system';</span></p>
<h3>Realizar la revisión general de requisitos.</h3>
<p>Consultar el URL correspondiente a  <span style="font-family: courier new,courier;">http://localhost/kohana/index.php</span>.  Si los requisitos se cumplen proceda con el siguiente paso, de lo contrario soluciónelos y vuelva a ejecutar la revisión.</p>
<p><span style="font-family: courier new,courier;">$ rm install.php</span></p>
<h3>Realizar la configuración general (segunda parte).</h3>
<p><span style="font-family: courier new,courier;">$ vi application/bootstrap.php</span></p>
<pre class="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' =&gt; '/kohana/'));

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

// Establece el estilo de ruta y el controlador/acción por defecto.
Route::set('default', '(&lt;controller&gt;(/&lt;action&gt;(/&lt;id&gt;)))')
  -&gt;defaults(array(
              'controller' =&gt; 'main',
              'action'     =&gt; 'index',
   ));</pre>
<h3>Consultar la documentación del framework.</h3>
<p>Acceder a la URL correspondiente a la siguiente de acuerdo a las rutas exactas de instalación.
</p>
<p style="padding-left: 30px;">http://localhost/kohana/index.php/guide</p>
<h2>Enlaces.</h2>
<ul>
<li>Kohana PHP Framework.<br />
<a href="http://kohanaphp.com/" >http://kohanaphp.com/</a></li>
<li>Página del proyecto de Kohana 3.<br />
<a href="http://dev.kohanaphp.com/projects/kohana3" >http://dev.kohanaphp.com/projects/kohana3</a></li>
<li>GIT del proyecto de Kohana 3.<br />
<a href="http://github.com/kohana/kohana" >http://github.com/kohana/kohana</a></li>
<li>Codeigniter.<br />
<a href="http://codeigniter.com/" >http://codeigniter.com/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/10/instalacion-basica-de-kohana-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como crear un mapa con GoogleMaps version 2, en pasos simples</title>
		<link>http://blog.jorgeivanmeza.com/2009/09/como-crear-un-mapa-con-googlemaps-version-2-en-pasos-simples/</link>
		<comments>http://blog.jorgeivanmeza.com/2009/09/como-crear-un-mapa-con-googlemaps-version-2-en-pasos-simples/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 20:02:34 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[GoogleMaps]]></category>
		<category><![CDATA[Hiper]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2022</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>Utilizar el API de <a href="http://maps.google.com/" >Google Maps</a> 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 <a href="http://maps.google.com/" >maps.google.com</a> 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.</p>
<p>En otras ocasiones me he referido a los <a href="http://blog.jorgeivanmeza.com/tag/GoogleMapplets/" >Mapplets</a> por esto la implementación de hoy la vamos a realizar utilizando el API síncrono.</p>
<h2>Objetivo.</h2>
<p>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.</p>
<div id="attachment_2024" class="wp-caption aligncenter" style="width: 650px"><a href="http://blog.jorgeivanmeza.com/wp-content/uploads/2009/09/Objetivo_Cuba5.png"><img class="size-full wp-image-2024" title="Objetivo_Cuba5" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2009/09/Objetivo_Cuba5.png" alt="Resultado final" width="640" height="478" /></a><p class="wp-caption-text">Resultado final</p></div>
<h2>Procedimiento.</h2>
<h3>Condiciones inciales.</h3>
<p>Para el desarrollo de esta mini aplicación vamos a utilizar PHP y <a href="http://en.wikipedia.org/wiki/Vanilla_software" >vanilla</a> Javascript, es decir, no nos apoyaremos en ningún <em>framework</em> de Javascript adicional a lo comúnmente soportado por los navegadores web actuales.</p>
<p>En mi caso, mi servidor web de destino será <a href="http://demo.jorgeivanmeza.com/" >http://demo.jorgeivanmeza.com/</a>.  Es muy importante determinar esto para la próxima etapa, la creación de la llave del API.</p>
<h3>Creación de la llave del API.</h3>
<p>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 <a href="http://localhost/" >http://localhost/</a> 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.</p>
<p style="padding-left: 30px;"><a href="http://code.google.com/apis/maps/signup.html" >http://code.google.com/apis/maps/signup.html</a></p>
<p>Es necesario contar con una cuenta de Google, así que de no contar con una es necesario <a href="http://mail.google.com/mail/signup" >abrirla</a> antes de intentar crear una llave del API.</p>
<h3>Creación de una estructura básica para la página web.</h3>
<p>Cree el archivo <span style="font-family: courier new,courier;">simpleGoogleMaps.php</span> (o como desee llamarlo) en una ubicación pública de su servidor web (bajo el <span style="font-family: courier new,courier;">DOCUMENT_ROOT</span>).  Agregue siguiente contenido al archivo y guárdelo.</p>
<pre class="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns='http://www.w3.org/1999/xhtml'&gt;
&lt;head&gt;
    &lt;meta http-equiv="Content-type" content="text/html; charset=utf-8" /&gt;
    &lt;meta name="Author" content="Jorge Iván Meza Martínez - http://jorgeivanmeza.com/ - jimezam@gmail.com" /&gt;
    &lt;meta name="Description" content="Demostración Simple de Google Maps" /&gt;

    &lt;title&gt;Demostración Simple de Google Maps&lt;/title&gt;

    &lt;!-- Llave del API --&gt;

    &lt;!-- Estilos CSS --&gt;

    &lt;!-- Implementación Javascript --&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;!-- Ubicación del mapa --&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h3>Especificar la Llave del API.</h3>
<p>En el contenido del archivo PHP actualice el siguiente código por la marca de <span style="font-family: courier new,courier;">Llave del API</span>.</p>
<pre class="php">&lt;script src='http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;hl=es&amp;key=XXXXX' type='text/javascript'&gt;&lt;/script&gt;</pre>
<p>Reemplace la cadena <span style="font-family: courier new,courier;">XXXXX</span> por su Llave del API específica que obtuvo durante el paso anterior correspondiente.</p>
<h3>Especificar la ubicación del mapa.</h3>
<p>El mapa se generará en un <span style="font-family: courier new,courier;">div</span> que determinemos dentro del <span style="font-family: courier new,courier;">body</span> 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 <span style="font-family: courier new,courier;">div</span>.</p>
<p>Reemplace la etiqueta <span style="font-family: courier new,courier;">Ubicación del mapa</span> con el siguiente código.</p>
<pre class="php">&lt;div id='MiMapa'&gt;Aqui viene el mapa!&lt;/div&gt;</pre>
<p>Es necesario identificar al <span style="font-family: courier new,courier;">div</span> con un <span style="font-family: courier new,courier;">id</span> único que utilizaremos posteriormente.</p>
<h3>Actualizar el estilo del mapa.</h3>
<p>El siguiente paso es el especificar un estilo para el <span style="font-family: courier new,courier;">div</span> 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.</p>
<p>Reemplace la etiqueta <span style="font-family: courier new,courier;">Estilos CSS</span> con el siguiente código.</p>
<pre class="css">&lt;style content="text/css"&gt;

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

&lt;/style&gt;</pre>
<h3>Especificar la implementación Javascript.</h3>
<p>El código faltante hace referencia a código Javascript que va a determinar el contenido y comportamiento del mapa.  Reemplace la etiqueta <span style="font-family: courier new,courier;">Implementación Javascript</span> con el siguiente código base.</p>
<pre class="javascript">&lt;script type='text/javascript'&gt;
// El código de las siguiente secciones se incluye aquí ...
&lt;/script&gt;</pre>
<h3>Preparar el mapa.</h3>
<p>Para crear el mapa y establecer sus parámetros iniciales se realizan las siguientes acciones.</p>
<ol>
<li>Verificar que exista la compatibilidad adecuada con el navegador.</li>
<li>Crear la instancia del mapa asociada al <span style="font-family: courier new,courier;">div</span> especifico.</li>
<li>Establecer la ubicación inicial del mapa.</li>
<li>Establecer el tipo inicial del mapa.</li>
</ol>
<p>Para hacer esto creamos al objeto <span style="font-family: courier new,courier;">mapa1</span> y a la función <span style="font-family: comic sans ms,sans-serif;">prepararMapa</span> con el siguiente código.</p>
<pre class="javascript">/*
 * 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;
}</pre>
<h3>Agregar un marcador.</h3>
<p>Posteriormente implementamos la función <span style="font-family: courier new,courier;">agregarMarcador</span> que se ocupará de agregar un marcador creado con cierta información específica al mapa.  Su código es el siguiente.</p>
<pre class="javascript">/*
 * 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);
 }</pre>
<h3>Información de las ciudades de Cuba.</h3>
<p>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.</p>
<pre class="javascript">/* 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
    }
 );</pre>
<p>Para automatizar el proceso de agregación de los marcadores basados en la información de los <span style="font-family: courier new,courier;">puntos</span> creamos a la función <span style="font-family: courier new,courier;">agregarMarcadores</span> cuya misión es la de invocar repetidas veces a la función <span style="font-family: courier new,courier;">agregarMarcador</span>.  En ella se define además el contenido del globito de cada uno de las ciudades (<span style="font-family: courier new,courier;">mensaje</span>).</p>
<pre class="javascript">/*
 * 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&lt;informacion.length; i++)
    {
        var nombre   = puntos[i]['nombre'];
        var latitud  = puntos[i]['latitud'];
        var longitud = puntos[i]['longitud'];

        var mensaje  = "Este es &lt;b&gt;" + nombre + "&lt;/b&gt;,&lt;br /&gt; su latitud es &lt;b&gt;" +
                       latitud + "&lt;/b&gt;&lt;br /&gt; y su longitud es &lt;b&gt;" + longitud + "&lt;/b&gt;.";

        agregarMarcador(mapa, latitud, longitud, mensaje);
    }
 }</pre>
<h3>Finalmente, el programa principal.</h3>
<p>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 (<span style="font-family: courier new,courier;">onLoad</span>) y desarrolla las siguiente actividades.</p>
<ol>
<li>Prepara el mapa.</li>
<li>Verifica que el mapa haya sido creado exitosamente.</li>
<li>Agrega los marcadores sobre las ciudades especificadas.</li>
</ol>
<p>Su código es el siguiente.</p>
<pre class="javascript">/* 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;
}</pre>
<h3>Listo!</h3>
<p>Probar la página web utilizando un navegador como <a href="http://getfirefox.com/" >Firefox</a>.</p>
<h2>Enlaces.</h2>
<ul>
<li>Programa de demostración - versión 0.1.<br />
<a href="http://demo.jorgeivanmeza.com/GMaps/SimpleDemoCuba/" >http://demo.jorgeivanmeza.com/GMaps/SimpleDemoCuba/</a></li>
<li>Google Maps API Versión 2.<br />
<a href="http://code.google.com/apis/maps/" >http://code.google.com/apis/maps/</a></li>
<li>Abrir una cuenta de usuario con Google.<br />
<a href="http://mail.google.com/mail/signup" >http://mail.google.com/mail/signup</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/09/como-crear-un-mapa-con-googlemaps-version-2-en-pasos-simples/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Algunas funciones del manejo de variables en PHP que acostumbro olvidar</title>
		<link>http://blog.jorgeivanmeza.com/2009/09/algunas-funciones-del-manejo-de-variables-en-php-que-acostumbro-olvidar/</link>
		<comments>http://blog.jorgeivanmeza.com/2009/09/algunas-funciones-del-manejo-de-variables-en-php-que-acostumbro-olvidar/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 17:28:31 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=2014</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<h2>Conversiones de tipos de datos.</h2>
<ul>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.doubleval.php" >doubleval</a>($mixed)</span> o <span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.floatval.php" >floatval</a>($mixed)</span>: convierte el valor de <span style="font-family: courier new,courier;">$mixed</span> a su representación de punto flotante.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.intval.php" >intval</a>($mixed[, $base=10])</span>: convierte el valor de <span style="font-family: courier new,courier;">$mixed</span> a su representación entera en la <span style="font-family: courier new,courier;">$base</span> especificada.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.strval.php" >strval</a>($mixed)</span>: convierte el valor de <span style="font-family: courier new,courier;">$mixed</span> a su representación en cadena.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.settype.php" >settype</a>($mixed, $type)</span>: convierte el valor de <span style="font-family: courier new,courier;">$mixed</span> a su correspondiente representación según el <span style="font-family: courier new,courier;">$type</span> seleccionado.  Los <span style="font-family: courier new,courier;">$type</span> válidos son: <span style="font-family: courier new,courier;">boolean</span> (<span style="font-family: courier new,courier;">bool</span>), <span style="font-family: courier new,courier;">integer</span> (<span style="font-family: courier new,courier;">int</span>), <span style="font-family: courier new,courier;">float</span>, <span style="font-family: courier new,courier;">string</span>, <span style="font-family: courier new,courier;">array</span>, <span style="font-family: courier new,courier;">object</span> y <span style="font-family: courier new,courier;">null</span>.</li>
</ul>
<h2>Verificación de tipos de datos.</h2>
<ul>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-array.php" >is_array</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es un arreglo.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-binary.php" >is_binary</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es una cadena binaria nativa.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-bool.php" >is_bool</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es un valor booleano.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-buffer.php" >is_buffer</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es un valor de cadena nativa binaria o Unicode.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-callable.php" >is_callable</a>($mixed)</span>: verifica si el contenido de<span style="font-family: courier new,courier;"> $mixed</span> puede invocarse como una función.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-double.php" >is_double</a>($mixed)</span>, <span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-float.php" >is_float</a>($mixed)</span> o <span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-real.php" >is_real</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es un valor real.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-int.php" >is_int</a>($mixed)<span style="font-family: times new roman,times;">,</span><span style="font-family: times new roman,times;"></span> <a href="http://www.php.net/manual/en/function.is-integer.php" >is_integer</a></span><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-int.php" ></a>($mixed)</span> <span style="font-family: courier new,courier;"><span style="font-family: times new roman,times;">o</span></span> <span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-long.php" >is_long</a><a href="http://www.php.net/manual/en/function.is-integer.php" ></a>($mixed)</span>: verifica si el contenido de <span style="font-family: courier new,courier;">$mixed</span> es un valor entero.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-null.php" >is_null</a>($mixed)</span>: verifica si el contenido de la variable <span style="font-family: courier new,courier;">$mixed</span> es <span style="font-family: courier new,courier;">null</span>.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-numeric.php" >is_numeric</a>($mixed)</span>: verifica si el contenido de la variable <span style="font-family: courier new,courier;">$mixed</span> es un número, independiente de si la variables es numérica o su representación en cadena.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-object.php" >is_object</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es una instancia de una clase.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-resource.php" >is_resource</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es una referencia a un recurso PHP.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-scalar.php" >is_scalar</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es un valor escalar, es decir, un entero, real, cadena o booleano.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-string.php" >is_string</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es una cadena.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.is-unicode.php" >is_unicode</a>($mixed)</span>: verifica si <span style="font-family: courier new,courier;">$mixed</span> es una cadena Unicode.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.gettype.php" >gettype</a>($mixed)</span>: obtiene el nombre del tipo de datos que representa <span style="font-family: courier new,courier;">$mixed</span>.  Los posibles tipos de datos obtenidos son: <span style="font-family: courier new,courier;">boolean</span>, <span style="font-family: courier new,courier;">integer</span>, <span style="font-family: courier new,courier;">double</span>, <span style="font-family: courier new,courier;">string</span>, <span style="font-family: courier new,courier;">array</span>, <span style="font-family: courier new,courier;">object</span>, <span style="font-family: courier new,courier;">resource</span>, <span style="font-family: courier new,courier;">NULL</span> y <span style="font-family: courier new,courier;">unknown type</span>.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.get-resource-type.php" >get_resource_type</a>($handle)</span>: obtiene el nombre del tipo de recurso referenciado por <span style="font-family: courier new,courier;">$handle</span>.</li>
</ul>
<h2>Serialización de información.</h2>
<ul>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.serialize.php" >serialize</a>($mixed)</span>: retorna la representación serializada de <span style="font-family: courier new,courier;">$mixed</span>.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.unserialize.php" >unserialize</a>($str)</span>: retorna la representación original de la variable serializada con <span style="font-family: courier new,courier;">$str</span>.</li>
</ul>
<h2>Existencia de las variables.</h2>
<ul>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.isset.php" >isset</a>($variable)</span>: verifica si la <span style="font-family: courier new,courier;">$variable</span> ha sido definida en el contexto.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.unset.php" >unset</a>($variable)</span>: destruye la definición de la <span style="font-family: courier new,courier;">$variable</span> en el contexto.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.get-defined-vars.php" >get_defined_vars</a>()</span>: retorna un arreglo asociativo con las variables definidas en el contexto.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.import-request-variables.php" >import_request_variables</a>($types[, $prefix])</span>: importa las variables contenidas en GET, POST o COOKIE en el contexto actual y con el <span style="font-family: courier new,courier;">$prefix</span> si se especificó.  Los posibles <span style="font-family: courier new,courier;">$types</span> por ende son una cadena con las combinaciones de las letras <span style="font-family: courier new,courier;">G</span>, <span style="font-family: courier new,courier;">P</span> y <span style="font-family: courier new,courier;">C</span>.</li>
</ul>
<h2>Impresión de las variables.</h2>
<ul>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.print-r.php" >print_r</a>($mixed[, $return])</span>: imprime recursivamente el contenido de <span style="font-family: courier new,courier;">$mixed</span>.  Si <span style="font-family: courier new,courier;">$return</span> es <span style="font-family: courier new,courier;">true</span> el resultado de la función no se imprime sino que se retorna.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.var-dump.php" >var_dump</a>($mixed1[, $mixed2, $mixed3, ...])</span>: imprime recursivamente el contenido de <span style="font-family: courier new,courier;">$mixed</span>(s) junto con su respectivo tipo de datos.</li>
<li><span style="font-family: courier new,courier;"><a href="http://www.php.net/manual/en/function.var-export.php" >var_export</a>($mixed[, $return])</span>: imprime recursivamente la representación de la variable <span style="font-family: courier new,courier;">$mixed</span>.  Si <span style="font-family: courier new,courier;">$return</span> es <span style="font-family: courier new,courier;">true</span> el resultado de la función no se imprime sino que se retorna.</li>
</ul>
<h2>Enlaces.</h2>
<ul>
<li>PHP Manual - Variable handling Functions.<br />
<a href="http://www.php.net/manual/en/ref.var.php" >http://www.php.net/manual/en/ref.var.php</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/09/algunas-funciones-del-manejo-de-variables-en-php-que-acostumbro-olvidar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Error en dotProject con la clase CTask</title>
		<link>http://www.marlonj.com/blog/2009/09/error-en-dotproject-con-la-clase-ctask/</link>
		<comments>http://www.marlonj.com/blog/2009/09/error-en-dotproject-con-la-clase-ctask/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 00:26:27 +0000</pubDate>
		<dc:creator>marlonj</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[Cacharreos]]></category>
		<category><![CDATA[dotproject]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[fix]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[universidad]]></category>

		<guid isPermaLink="false">http://www.marlonj.com/blog/?p=1950</guid>
		<description><![CDATA[Hace una semana, instale dotProject version 2.1.2 en el servidor de estudiantes de la Universidad para los grupos que estan trabajando TSP en Ingeniera de software, con el fin que realicen la planeacion y seguimiento del proyecto del semestre utilizando esta herramienta. El dia de hoy me conto uno de los integrantes del grupo C+- [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://www.marlonj.com/blog/wp-content/uploads/2009/09/logo_dotproject.png"><img class="alignleft size-full wp-image-1951" style="margin: 5px;" title="logo_dotproject" src="http://www.marlonj.com/blog/wp-content/uploads/2009/09/logo_dotproject.png" alt="logo_dotproject" width="250" height="86" /></a>Hace una semana, instale dotProject version 2.1.2 en el servidor de estudiantes de la Universidad para los grupos que estan trabajando TSP en Ingeniera de software, con el fin que realicen la planeacion y seguimiento del proyecto del semestre utilizando esta herramienta. El dia de hoy me conto uno de los integrantes del grupo C+- que el dotProject le estaba reportando un error con una sentencia SQL, asi que me di a la tarea de buscar la causa del problema y solucionarla.</p>
<p style="text-align: justify;"><strong>Error : </strong></p>
<pre style="text-align: justify;">.../query.class.php(623): query failed(SELECT COUNT(ut.*) AS user_task_count ...</pre>
<p style="text-align: justify;"><strong>Diagnostico : </strong></p>
<ul>
<li>Como se puede observar el error es causado por una sentencia SQL que no se puede ejecutar.</li>
<li>Buscando en algunos foros encontre que es debido a la forma como se cuentan los registros utilizando el alias de la tabla ut</li>
</ul>
<p><strong>Solucion : </strong></p>
<ul>
<li>Acceder al servidor donde se tiene el dotProject instalado</li>
<li>Editar el archivo :<br />
modules/tasks/tasks.class.php</li>
<li>Ir a la linea 1305</li>
<li>Modificar el COUNT removiendo el nombre del alias de la tabla<br />
COUNT(*)</li>
<li>Guardar el archivo</li>
<li>Problema solucionado</li>
</ul>
<p>Enlaces :</p>
<ul>
<li>Sitio Oficial de dotProject<br />
<a title="dotProject" href="http://www.dotproject.net" >http://www.dotproject.net</a></li>
<li>Foro de dotProject<br />
<a title="dotProject Forums" href="http://www.dotproject.net/vbulletin/archive/index.php?t-8745.html" >http://www.dotproject.net/vbulletin/archive/index.php?t-8745.html</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.marlonj.com/blog/2009/09/error-en-dotproject-con-la-clase-ctask/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como obtener los nodos de un tipo específico en Drupal 6 desde API</title>
		<link>http://blog.jorgeivanmeza.com/2009/08/como-obtener-los-nodos-de-un-tipo-especifico-en-drupal-6-desde-api/</link>
		<comments>http://blog.jorgeivanmeza.com/2009/08/como-obtener-los-nodos-de-un-tipo-especifico-en-drupal-6-desde-api/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 14:08:43 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Sindicados]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Hipergalaxia]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.jorgeivanmeza.com/?p=1994</guid>
		<description><![CDATA[Introducción.
En algunos casos puede ser útil obtener desde un fragmento de código PHP utilizando el API oficial, los nodos de un portal basado en Drupal 6 que correspondan con un tipo específico (file, story, event, page, ...).  Esto se puede hacer fácilmente de la siguiente manera.
Procedimiento.
Obtener el listado con la información general de los nodos [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción.</h2>
<p>En algunos casos puede ser útil obtener desde un fragmento de código PHP utilizando el API oficial, los nodos de un portal basado en Drupal 6 que correspondan con un tipo específico (<em>file</em>, <em>story</em>, <em>event</em>, <em>page</em>, ...).  Esto se puede hacer fácilmente de la siguiente manera.</p>
<h2>Procedimiento.</h2>
<p>Obtener el listado con la información general de los nodos del tipo específico.  Para esto se consulta la tabla <span style="font-family: courier new,courier;">node</span> que contiene la siguiente información de los nodos.</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">nid         int(10)           # ID del nodo.<br />
vid         int(10)           # ID de la versión del nodo.<br />
type        varchar(32)       # Tipo del nodo.<br />
title       varchar(255)      # Título.<br />
uid         int(11)           # ID del propietario.<br />
status      int(11)           # Estado (publicado = 1; sin publicar/oculto = 0)<br />
created     int(11)           # Timestamp de la creación del nodo.<br />
changed     int(11)           # Timestamp de la modificación del nodo.<br />
comment     int(11)           # Estado de comentarios (desactivados = 0; sólo lectura = 1; activados = 2).<br />
promote     int(11)           # Promocionado a la página principal (no = 0; si = 1).<br />
moderate    int(11)           # Moderado </span><span style="font-family: courier new,courier;">(no = 0; si = 1).</span><br />
<span style="font-family: courier new,courier;">sticky      int(11)           # Pegajoso </span><span style="font-family: courier new,courier;">(no = 0; si = 1).</span><br />
<span style="font-family: courier new,courier;">language    varchar(12)       # Código del idioma.<br />
tnid        int(10)<br />
translate   int(11)</span></p>
<p>La consulta básica se puede realizar de la siguiente manera.</p>
<pre class="php">$sql = "SELECT nid
        FROM {node}
        WHERE type = 'TIPO_DE_NODO' AND
              status = 1
        ORDER BY created DESC";

$results = db_query($sql);</pre>
<p>Posteriormente se iteran los resultados obtenidos de la consulta y se carga la información completa de cada uno de los nodos.</p>
<pre class="php">while ($result = db_fetch_object($results))
{
    $node = node_load($result -&gt; nid);
}</pre>
<p>El contenido del nodo recuperado dependerá en cierta medida de los módulos instalados que alteran su estructura.  Para mostrar por ejemplo el título, la fecha de creación, el mensaje y la fecha de modificación de una noticia se utiliza el siguiente fragmento.</p>
<pre class="php">echo 'Titulo: ' . $node -&gt; title . '&lt;br /&gt;';
echo 'Fecha: ' . format_date($node-&gt;created) . '&lt;br /&gt;';
echo 'Mensaje: ' . $node-&gt;body . '&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;';
echo 'changed on: ' . format_date($node-&gt;changed, 'custom', 'Y-m-d H:i:s O') . '&lt;br /&gt;';</pre>
<h2>Enlaces.</h2>
<ul>
<li>Headless Drupal: Using Drupal’s API to Batch Script Your Drupal Site.<br />
<a href="http://www.stonemind.net/blog/2009/01/20/headless-drupal-using-drupals-api-to-batch-script-your-drupal-site/" >http://www.stonemind.net/blog/2009/01/20/headless-drupal-using-drupals-api-to-batch-script-your-drupal-site/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/08/como-obtener-los-nodos-de-un-tipo-especifico-en-drupal-6-desde-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
