Como convertirse en un "Desarrollador PHP Senior" y no morir en el intento... escrito por Enrique Place
"Biscuit: otro framework PHP MVC"
Artículo completo en: EstadoBeta
"Modelo de objetos en PHP5"
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
Continúa leyendo su biografía en Wikipedia
"Llamadas dinámicas a funciones y métodos en PHP"
Artículo completo en: Es Lo Mas
Artículos varios sobre PHP
Nota: aunque no todos hablan exclusivamente sobre PHP5, se aplican sin problemas a todas las versiones, incluyendo la última.
- Introducción a PHP 5
- Un vistazo a PHP5
- PHP4 y PHP5 juntos, pero no revueltos
- FAQ del echo
- Guía de seguridad en PHP (Capítulo primero)
- Libreria ADOdb para PHP
- "Cómo hacer para optimizar PHP"
- Introducción a los Web Services en PHP
- Web Services con PHP
- Web Services: XML-RPC, SOAP, sobre PHP, Perl, y otros conceptos
- Memorias de un aprendiz de PHP
Pear: Crear formularios sencillos con la clase "HTML_Form"
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 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.
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.
<?
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)
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.
Ejemplo de Usoclass 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();
}
}
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)
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
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:
- Smarty:
date_format - PHP:
number_format
Entradas populares
-
He visto mucha documentación que habla sobre el tema de los métodos "getter / setter", o traducido al castellano los métodos ...
-
Esto es lo que pasa cuando tienes entornos que no son homogéneos y cada aplicación se encuentra ubicada en distintas márgenes de un "rí...
-
Uno de los problemas que me he encontrado con la versión 5 de PHP es la falta de la representación de los "paquetes" desde el prop...
-
Este es un resumen de conclusiones que se vertieron en una discusión sobre el tema en Foros de Web , donde se plantea la duda de si PHP5 ...
-
Este es un ejemplo publicado a partir de la duda de un usuario , y como son preguntas que se hacen reiteradamente, les dejo el ejemplo aquí ...
-
Esta reflexión se la escribo a todos los "Programadores PHP": Al día de hoy la mayoría de los institutos o universidades de muchos...
-
El Patrón " Singleton " sirve para cuando buscamos restringir la creación de instancias de un objeto, obligando que solo se pueda ...
-
Hace un tiempo que vengo recomendando esta presentación como punto de partida para definir un estándar de desarrollo en una empresa. En ambi...
-
Bueno, luego de revisarlo una y otra vez (y otra vez) ya se encuentra terminada la primer versión del libro que junta toda la experiencia ac...
-
Estoy viendo muy seguido en foros que frecuento regularmente a muchos programadores que quieren dar " el gran salto " y evolucion...