"Biscuit: otro framework PHP MVC"

"Framework basado en Ruby on Rails que transa muchas de las ventajas de la OOP con tal de ser extremádamente fácil de usar."

Artículo completo en: EstadoBeta

"Modelo de objetos en PHP5"

"El nuevo corazón de PHP, Zend Engine 2, incorpora un nuevo modelo de objetos, mucho más cercano a lenguajes totalmente orientados a objetos como Java.

Este artículo recoge y analiza algunas de las características más destacadas."


Artículo completo en: Epsilon Eridani

Rasmus Lerdorf, el creador de PHP

"En 1995 Rasmus Lerdorf quería saber cuántas personas estaban leyendo el curriculum vitae en su página web y para ello creo un CGI en Perl que mostraba el resultado estadístico en la propia página. Rasmus llamó a ese script PHP, acrónimo de Personal Home Page. Inmediatamente comenzó a recibir pedidos de muchas personas para obtener el pequeño programa y Rasmus lo compartió con ellas y creó una lista de correo para intercambiar opiniones, sugerencias y correcciones. Como resultado de todo esto, Rasmus accedió a un puesto en la Universidad de Toronto para crear un sistema administrado por web para que los estudiantes se conecten a Internet, mediante acceso discado, con control de cuentas de acceso en base horaria y reflejando todos los datos en tiempo real sobre una base de datos ..."

Continúa leyendo su biografía en Wikipedia

"Llamadas dinámicas a funciones y métodos en PHP"

"En PHP no existen los punteros, pero al ser un lenguaje interpretado es sencillo ofrecer funcionalidades similares. Disponemos de dos opciones, una la más simple, basada en llamar a funciones o métodos a partir de una variable string que contenga el nombre de la función o método, lo cual se denomina en PHP funciones variables, y otra, basada en la utilización de algunas funciones específicas de PHP, que nos ofrecen algo más de potencia que el caso anterior ..."

Artículo completo en: Es Lo Mas

Artículos varios sobre PHP

Estuve revisando los artículos que tengo guardados en mi cuenta de Gmail (me auto envío correos y tengo filtros para ir ordenándolos en "Etiquetas") y para que sean de provecho para otros desarrolladores (pues leo y descarto todos los días artículos y manuales) publicaré progresivamente enlaces que considero útiles y de buena calidad:

Nota: aunque no todos hablan exclusivamente sobre PHP5, se aplican sin problemas a todas las versiones, incluyendo la última.

Pear: Crear formularios sencillos con la clase "HTML_Form"

Para este ejemplo vamos a asumir que estamos usando el motor de base de datos MySQL y una base de datos "prueba", donde crearemos un formulario para solicitar el id del cliente y luego consultar la base de datos para recuperar la información del mismo.

Debemos crear la tabla "clientes" que contendrá los siguientes campos: id y nombre.

Este es el código de nuestro "formulario.php":


<?php
require_once "HTML/Form.php";
$form = new HTML_Form('consulta.php');
$form->addText("id", "Número de cliente?");
$form->addSubmit("submit", "Consultar");
$form->display();
?>


Creamos nuestro primer formulario usando la clase "HTML_Form", donde en el constructor de la clase definimos cual será el programa que se encargará de procesar la información del formulario y hacer la consulta SQL (consulta.php). Creamos un campo para recibir el número de id (método addText) y el botón de "Consultar" (método addSubmit).

<?php
require_once 'DB.php';
$db =& DB::connect('mysql://root:@localhost/prueba');
if (PEAR::isError($db)) {
die($db->getMessage());
}

$db->setFetchMode(DB_FETCHMODE _ASSOC);
$sql = "SELECT * FROM clientes";
if($_GET['id']<>""){
$sql .= " WHERE id='".$_GET['id']."'";
}
$res =& $db->query($sql);

while ($res->fetchInto($row)) {
print_r($row);
}
?>

En el archivo "consulta.php" recibimos el valor cargado en el formulario ($_GET['id']) y si este tiene un valor (es distinto de cero) se crea una sentencia SQL para obtener el cliente, de lo contrario traerá todos los clientes.

Simple, directo y sencillo. Con el framework Pear pudimos armar la parte de la "presentación" (el formulario) y parte de la "persistencia" (con el resultado).

¿Cómo instalar rápidamente Smarty?

El problema

El template Smarty puede tener algunas dificultades a la hora de instalarlo:
  • No tenemos control del servidor donde alojamos nuestro sitio, solo de un directorio.
  • No tenemos conocimientos suficientes para configurar el servidor web.
  • Hemos seguido el tutorial de la página oficial pero tuvimos problemas al entenderlo o simplemente no pudimos seguir los pasos.
  • Estamos en Windows usando algún software que nos provee el entorno de desarrollo (Apache, PHP, MySQL, etc) pero no Smarty, y el tutorial de instalación no contempla este contexto.
  • etcétera.
Introducción

El template Smarty, al final de cuentas, es un conjunto reducido de clases que ofrecen la funcionalidad de "templates html" para nuestros desarrollos basados en PHP, donde terminamos usando una instancia (POO) para manipular la información y el comportamiento del motor de templates.

Una solución fácil y rápida

Bajar el paquete Smarty y descomprimirlo en el directorio donde se encuentra nuestro sitio web. Si no tenemos acceso a la línea de comandos en el servidor, lo bajamos en nuestro equipo de desarrollo, descomprimimos el paquete, y luego subimos el directorio entero a nuestro sitio.

Por ejemplo

Si el directorio en el servidor web es "/var/www/" y el directorio de nuestro sitio es "misitiopersonal", la ruta completa sería "/var/www/misitiopersonal".

Si nos bajamos el paquete de Smarty del sitio oficial, este vendrá comprimido y la nomenclatura del mismo será: "Smarty-2.6.10", donde la información que precede al guión hace referencia a la versión del mismo.

Tips: si queremos simplificar la instalación, configuración y uso del template, podemos modificar el nombre del directorio (o crear un link) a uno abreviado. Por ejemplo: solo "Smarty".

Los directorios que necesitamos

Se necesitan por lo menos los siguientes directorios:
  • templates: este directorio contendrá los templates para nuestras páginas web, es decir, los archivos .html que contienen código html con la posibilidad de ser invocado desde un PHP.
  • templates_c: es el directorio temporal donde el sistema lee los templates del directorio anterior y genera un nuevo html de forma dinámica con el código resuelto, es decir, código html y la sustitución de todas las variables cargadas y las sentencias propias resultas por el Smarty. Este resultado es la "página final", lo que recibirá el usuario cuando navegue nuestro sitio web.
Luego, creamos el siguiente archivo PHP para probar el template.



<?
require_once("Smarty/libs/Smarty.class.php");

$miSmarty = new Smarty();

$miSmarty->template_dir = 'templates';
$miSmarty->config_dir = 'config';
$miSmarty->cache_dir = 'cache';
$miSmarty->compile_dir = 'templates_c';

$miSmarty->assign("titulo", "Formulario de Consultas");
$miSmarty->display("formulario.tpl.html");
?>

Incluimos la clase base "Smarty.class.php" y luego creamos la primer instancia de nuestro template, modificamos los atributos de la clase para definir donde estarán los directorios necesarios para su trabajo y creamos una variable del template (assign) y le cargamos el título del formulario ("Formulario de Consultas").

Finalmente, invocamos el template con el método "display".

Nuestro primer template

Podemos usar la nomenclatura que más nos guste; en este caso seguimos los ejemplos de la documentación oficial: nombredearchivo.tpl.html, donde "tpl" es la abreviación de template y obviamente "html" porque es un archivo con ese formato. Esto último es útil para poder editar el archivo en nuestro editor HTML de preferencia.

Deberemos tener creado el archivo "formulario.tpl.html" en el directorio "template" con el siguiente contenido:

{$titulo}

Donde el "{$titulo}" será sustituido con el contenido especificado en archivo PHP.

En Resumen

Logramos instalar Smarty sin depender de la configuración del servidor, sin necesitar tener acceso como administradores. Logramos modificar su comportamiento, creamos la primer instancia del objeto y logramos ejecutar el primer template.

Ahora que el entorno está pronto, tenemos el camino abierto para aprender a usarlo, solo queda leer el manual! ;-)

En próximos artículos abordaremos los temas iniciales de como empezar a usar el motor de templates Smarty.

¡Saludos!

¿Cómo se implementa el patrón "Factory Method" en PHP5? (revisado 7/11/2006)

Siguiendo en la línea del artículo anterior sobre el tema Patrones de Diseño, donde se trataba en particular el patrón "Factory Method" en PHP4", se implementará un ejemplo aprovechando las nuevas características que ofrece la versión 5 de PHP.

Descargos al respecto

Los "patrones de diseño" se representan con diagramas UML y son una guía para su implementación. No necesariamente se puede/debe implementar el patrón de la misma forma en todos los lenguajes, y nosotros además podemos modificarlos para adaptarlos a nuestras necesidades particulares.

Implementación

Se definen dos clases, "Conductor" y "Vehiculo", y una "Fábrica" de objetos que tendrá la responsabilidad de crear a demanda las instancias de esas clases.

class Conductor{

function
__toString() {

return
"Soy un Conductor";

}

}

class
Vehiculo{

function
__toString(){

return
"Soy un Vehiculo";

}

}

abstract class Fabrica {

public static function crear($tipo){

return new
$tipo();

}

}

Ejemplo de Uso
echo Fabrica::crear("Conductor");

echo
Fabrica::crear("Vehiculo");
En ambos casos usamos la "Fabrica" sin tener la necesidad de instanciarla, invocando directamente a la clase y usando el método "crear". La fábrica necesita recibir por parámetro el nombre de la clase del objeto que se desea crear, y ella nos devolverá una instancia de la clase solicitada.

Sobre el "toString"

Como las clases implementan los métodos "toString", cuando hacemos "echo" de la instancia recibida, el método es invocado automáticamente y nos devuelve la descripción del objeto.

El "toString" es un concepto muy usado en la POO: generalmente es un método reservado (como el constructor, el destructor, etc) y por definición es la forma estándar de convertir un objeto en String.

Resumen final

La ventaja de este "patrón de diseño" es que tenemos centralizada la creación de objetos en una entidad que a pedido nos devuelve instancias de los mismos. Es una forma de tener el control de la creación de objetos, y donde podemos agregar procedimientos para registrar cada creación y actuar en consecuencia (estadísticas, seguridad, etc).

¡Saludos, hasta el próximo patrón!

Pear: ¿Cómo abstraer nuestra conexión con la base de datos?


En este pequeño ejemplo nos vamos a introducir en el uso del Framework PEAR", y en particular hemos seleccionado la "clase" (concepto de la programación orientada a objetos) para hacer la "abstracción de la base de datos".


La idea es tener "algo" entre medio de "nuestro sistema" y la "base de datos" que nos "oculte" la complejidad de la misma y toda dependencia con ella.


Si nosotros programáramos usando directamente las sentencias (o funciones) que nos provee el propio lenguaje, estaríamos atados de forma explícita a la base de datos.


Por ejemplo, disponemos de funciones como:



$con = mysql_connect($cadena_de_conexion);
$result = mysql_query('SELECT * FROM clientes', $con);
while ($row = mysql_fetch_row($result)) {
echo $row[0] . ': ' . $row[1] . "\n";
}
mysql_free_result($result);
msql_close();
?>


Este ejemplo está hecho con funciones donde explicitan cual es nuestra base de datos (mysql_connect, mysql_query, etc). Si en un futuro deseamos cambiar de motor a PostgreSQL (por ejemplo) deberíamos recorrer todos nuestros fuentes que usen la base y sustituir por las funciones correspondientes: pg_connect, pg_query.


Es evidente que volveríamos a tener el mismo problema si en un futuro necesitáramos cambiar nuevamente de base, por ejemplo, a Oracle.


Una solución es usar "algo" que nos "abstraiga" del trabajo con la base de datos; en este caso nos apoyaremos en una de las clases disponibles del Framework Pear: "DB"




require_once 'DB.php';
$db =& DB::connect('mysql://root:@localhost/prueba');
$result =& $db->query('SELECT * FROM clientes');
while ($result->fetchInto($row)) {
echo $row[0] . ': ' . $row[1] . "\n";
}
$db->free();
$db->disconnect();
?>


Si nos encontramos que debos cambiar de motor de base de datos, solo deberíamos cambiar cambiar el nombre de "motor" en la cadena de conexión (mysql -> pgsql).


Alguien podría decir que lo único que mejoramos es que en vez de cambiar muchas líneas explícitas sobre MySQL ahora debemos cambiar una (la cadena de conexión) en todos nuestros fuentes.


La idea es hacer un ejemplo rápido para explicar de forma fácil las ventajas de esta forma de trabajo. Se me ocurren tres alternativas rápidas para solucionar estos inconvenientes:



  • Creamos un archivo con la sintaxis de conexión y lo incluimos en todos nuestros fuentes. Cuando se necesite cambiar la cadena, solo se deberá modificar un solo fuente.

  • Creamos un archivo de configuración que define "constantes" y luego estas se usan en todas las cadenas de conexión.

  • Creamos nuestra propia clase "BaseDeDatos" que en su estructura tienen los atributos cargados con valores por defecto que definen como será nuestra conexión a la base. Modificamos los atributos de la clase, y cambia el comportamiento de la conexión.


La última opción es la que prefiero, pues agregamos una nueva capa de abstracción que nos abstrae ahora de la capa de abstracción de Pear (valga todo lo redundante que fui).

¿Cual es el beneficio de esto?

Estamos protegidos ante un nuevo potencial problema: que debamos cambiar la clase "DB" por otra que ofrezca mayores funcionalidades, lo que nos obligaría a modificar todos nuestros fuentes nuevamente y agregar la sintaxis de la nueva clase de abstracción!



¿Fantástico, no? ;-)



¡Saludos abstractos!

Patrón de Diseño "Singleton" (revisado 7/11/2006)


El Patrón "Singleton" sirve para cuando buscamos restringir la creación de instancias de un objeto, obligando que solo se pueda crear una única instancia (de ahí su nombre).

Un caso hipotético de aplicación podría ser: tenemos una clase BaseDeDatos que nos devuelve un objeto llamado "bd" una vez creada la conexión con la base de datos. En vez de permitir que las aplicaciones usen libremente la clase y puedan crear tantas instancias del objeto "Base de Datos" como aplicaciones y accesos a bases existan, se decide restringir la creación a una sola instancia y esta será compartida y usada por todos.

¿Cómo funciona el patrón de diseño Singleton?

La forma de proceder del patrón es la siguiente: si se solicita una instancia del objeto:

a) si no existe (o sea, la primera vez que se usa) se crea la instancia.

b) si existe una instancia (es la segunda o más vez que se usa), devuelvo la existente, todas las veces que se me solicite.

c) el constructor de la clase debe permanecer "anulado" definiéndolo como "privado". De esta forma se asegura que no se puedan crear instancias de forma directa y solo se permite a través del método "getInstancia()":

class Singleton {
    static
private $instancia = NULL;

   private function __construct() {}

    static
public function getInstancia() {
       if (
self::$instancia == NULL) {
         
self::$instancia = new Singleton ();
       }
       return
self::$instancia;
    }
}
// Ejemplo de uso

// Le pido al Singleton que me de una instancia
// del objeto. Como no existe, la crea.

// Nota: si hacemos "echo" de un objeto que no
// tiene implementado el método toString,
// el sistema despliega el número único que
// representa al objeto creado.

$inst1 = Singleton::getInstancia();
echo
$inst1;

// En el segundo caso, como existe la instancia,
// no la crea, y la entrega directamente.

$inst2 = Singleton::getInstancia();
echo
$inst2;


¿Ventajas/usos?

Como dice la introducción, tenemos controlada la creación de objetos y podremos además disminuir el uso de memoria al tener una sola instancia que se usa en todo el contexto de la aplicación.

¿Cómo se implementa el patrón "Factory Method" en PHP4? (revisado: 7/11/2006)

En el mundo del "Diseño de Software" existe algo que se llama "Patrones de Diseño". Los patrones de diseño son -mi definición rápida- "la mejor solución probada y documentada que puede aplicarse a un problema conocido y recurrente".

Evitan que reinventemos la rueda para resolver problemas conocidos, y a su vez, hasta nos sirven de modelo para hacer soluciones "reutilizables" y "extensibles" (más información buscar por "principios de diseño de software orientado a objetos").

Existen muchos "patrones" (y a su vez muchos "catálogos" de patrones; el más famoso es el GOF) y el que quiero mostrar como ejemplo es el "Pattern Factory Method" ("Patrón Método Fábrica").

La intención de este patrón es concentrar la creación de los objetos a través de una clase, como forma de control, de orden, o para ocultar complejidad, para que los objetos no se estén creando libremente por todo nuestro sistema. De ahora en más, le pediremos a la Fábrica que nos fabrique el objeto que estamos necesitando.

// Clase Abstracta
class Compra{
    function
Compra(){
    }
    function
toString(){
    }
}

// Heredo de la clase abstracta
class CompraDirecta extends Compra{
    function
CompraDirecta(){
    }
    function
toString(){
       echo
"soy CD";
    }
}

// Heredo de la clase abstracta
class Licitacion extends Compra{
    function
Licitacion(){
    }
    function
toString(){
       echo
"soy Licitacion";
    }
}

// Construcción de la clase "Fábrica"
class Factory{
    var
$obj;
    function
Factory(){
    }
    function
crear($tipo){
       
$this->obj = new $tipo();
       return
$this->obj;
    }
}

// Ejemplo de Uso

// Creo la "fábrica"
$miFact = new Factory();

// Defino un objeto "genérico" y que luego
// la fábrica se encarga de crear según el
// parámetro que reciba.

// En este caso, miCompra se crea como una
// instancia de la clase "CompraDirecta"

$miCompra = $miFact->crear(CompraDirecta);
$miCompra->toString();

// En este caso, miCompra se crea como una
// instancia de la clase "Licitacion"

$miCompra = $miFact->crear(Licitacion);
$miCompra->toString();

Y listo, tengo mi fábrica de objetos "Compras", la cual cuenta con una clase abstracta donde puedo incluir todo el esqueleto común de las compras, y luego, al crear la clase según el tipo de compra, puedo definir sus particularidades.

Si mañana necesito agregar un tipo de compra, por ejemplo "Compra Centralizada", creo una clase con este nombre, heredo de la clase abstracta "Compra" y defino sus particularidades.

No hubo que modificar el código existente ("cerrado al cambio") y se pudo extender su funcionalidad ("abierto a la extensión").

Notas sobre el ejemplo implementado:
  • No hay que olvidar que PHP4 no cuenta con "interfaces", ni con métodos "toString", ni con "clases abstractas", algo que siempre tuvo Java y que ahora lo implementa PHP5 (éramos tan pobres...)

PD: Carlos Cantonnet, gracias por tus clases de UML! ;-)

Que lo disfruten!

Artículo relacionado: ¿Cómo se implementa el patrón "Factory Method" en PHP5?"

Smarty: Formato numérico y formato de fecha

En mi trabajo uso constantemente PHP, y para separar la "capa de presentación" de la "lógica del negocio", uso Smarty, el template por naturaleza para PHP (de la misma forma, el framework Pear) ;-)

Hace poco terminé con lo fundamental de la reingeniería del portal para el cual trabajo, lo que me llevó más de lo esperado (lo que no es raro tampoco, en mi experiencia ;-). Por suerte, pude decir que toda la lógica y la presentación, en esencia, estaba concluida.

Nota: La idea de la "capa de presentación" es, a grandes rasgos, que la "lógica" procese, y la "presentación" muestre, o le de formato, a la información que recibe de la lógica.

Separar las "responsabilidades" en capas; que una capa no haga el trabajo de la otra, es fundamental.

Terminé primero, según lo dicta las leyes del buen programador sobreviviente, con todas las tareas que ofrecían el mayor valor agregado desde el punto de vista de los usuarios y los clientes del sitio (que no son lo mismo), y dejé para lo último las tareas menores (títulos, fechas, redondeos, formatos, etc).

Generalmente mi suerte no me ayuda en estos casos, y lo que pensé que era solo 30 minutos, se transformó en tarea de un par de horas.

Y como resumen, quiero dejar para la posteridad, los resultados:


  • Tags del Template: En Smarty se usan los {} para encerrar el código referente al template y separarlo del código puro html. Hace tiempo que modifico la configuración para que use la combinación de tag de html (Escaping Smarty Parsing). El resultado es que puedes levantar el código del template, que generalmente tiene de extensión ".tpl.html", en cualquier editor html y no verás los tag's del template. Esto es muy útil para cuando quieres delegar este tipo de trabajos a alguien que se dedique al diseño gráfico, etc.

  • Formato de Fecha: Si quieres darle formato a la fecha, deberás hacer lo siguiente:

    {$fecha | date_format:"%d/%m/%Y"}

    Recibe: "2005-04-26" Devuelve: "26/04/2005"
    {$fecha | date_format:"%A %d/%m/%Y - %H:%M hs."
    | capitalize}

    Recibe: "2005-05-04 16:00:00-03" Devuelve: "Miércoles 04/05/2005 - 16:00 Hs."



  • Formato numérico: Esto fue más difícil, pues la documentación tanto de Smarty como de PHP es muy escueta. Lo natural es que los números se muestren solo con el separador "." en los decimales. El tema se complica cuando quieres que el separador de decimales sea una ",", y los miles un ".". La solución (que me llevó una hora, y espero ahorrarles ese tiempo):
    {$importe|number_format:2:',':'.'}

    Recibe: "1808029.63"
    Devuelve: "1.808.029,63"


Referencias:

Entradas populares