Instalación de Lighttpd y PHP bajo Windows

Software, Web, Windows December 1st, 2008

Lighttpd (alias Lighty) es una alternativa rápida y liviana al ya muy conocido servidor de páginas Apache y que incluye soporte para diversas características como FastCGI, SCGI, Auth, Output-Compression y URL-Rewriting entre otras. La idea de este artículo es la de experimentar con el trabajando con PHP para empezar a determinar si es o no idóneo para despliegues de aplicaciones web en equipos de bajo perfil.

Instalación de LightTPD.

Descargar la versión apropiada desde el proyecto WLMP: http://en.wlmp-project.net/downloads.php. Para este caso se eligió la versión ZIP de la versión 1.4.20-1 con soporte SSL de sólo el servidor web (sin MySQL ni demás): LightTPD-1.4.20-1-Win32-SSL.zip.

Descomprimirla y ubicar el directorio LightTPD en su ubicación final.

Ejecutar el script de prueba TestMode.bat.

Si utiliza Windows Vista el sistema le solicitará confirmar el acceso de la aplicación con un diálogo similar al mostrado a continuación. Presione el botón Desbloquear para continuar e incluir la excepción "A fast, secure and flexible webserver" en el firewall.

Advertencia del firewall

Advertencia del firewall

Una ventana de Símbolo del sistema se deberá haber abierto mostrando la salida estándar y salida de error del servidor. Accediendo a http://localhost/ deberá mostrarse una página web como la siguiente.

Instalación exitosa

Instalación exitosa

Por defecto el árbol de archivos públicos se ubica en <ruta>\LightTPD\htdocs y las opciones de configuración bajo <ruta>\LightTPD\conf.

  • lighttpd-inc.conf - archivo de configuración por defecto.
  • lighttpd-srv.conf - información de registro para el servicio.
  • lighttpd-tag.conf - información de etiquetado del servidor.
  • lighttpd-auth.conf - archivo de autenticación de usuarios para mod_auth.

Hasta ahora Lighttpd está ocupando 1480KB de memoria.

Consumo de memoria #1

Consumo de memoria #1

Presione la combinación CTRL+C en la ventana de Símbolo del sistema para finalizar la ejecución de prueba.

Configuración de PHP como FastCGI.

Ejecutar PHP como FastCGI versus CGI convencional acostumbra a ser mas eficiente ya que a diferencia de CGI que debe invocar una instancia de php-cgi.exe cada vez que se procesa un archivo .php, FastCGI administra una serie de procesos hijos que se ejecutan constantemente en background y que pueden ser accedidos de la manera equipo:puerto, sockets de Unix o pipes.

Las siguientes modificaciones se realizarán en el archivo <ruta>\LightTPD\htdocs\lighttpd-inc.conf.

Activar el módulo mod_fastcgi removiendo el comentario (#) al comienzo de la línea.

server.modules              = (

                                "mod_access",

                                "mod_accesslog",

                                "mod_alias",

                                "mod_fastcgi",

                                "mod_ssi",

                                "mod_status",

                               )

Modifique la ubicación del árbol de directorios (document-root) especificando su ubicación absoluta en lugar de la relativa.

server.document-root        = "<ruta>/LightTPD/HTDOCS/"

Active la configuración del fastcgi.server removiendo los comentarios de las líneas apropiadas y configúrelo de la siguiente manera.

fastcgi.server = ( ".php" =>

                   ( "localhost" =>

                     (

                       "host" => "127.0.0.1",

                       "port" => 10000,

                       "broken-scriptfilename" => "enable"

                      )

                    )

                  )

Instalación de PHP.

Descargue los paquetes de la distribución de PHP que requiera desde el sitio de descargas http://www.php.net/downloads.php.

Para este caso se utilizó el paquete PHP 5.2.6 installer únicamente.

Ejecute el archivo recién descargado.

Elija una ubicación (destination folder) de acuerdo a sus necesidades. Para este caso será <ruta>\LightTPD\PHP.

Como tipo de servidor (Web Server Setup) elija Otro CGI (Other CGI) ya que se va a realizar una instalación independiente de FastCGI.

En la selección de items para instalar (Choose Items to Install) bajo la rama Extensions seleccione las extensiones que requiera. Para esta instalación se eligieron los siguientes.

  • Crack.
  • Curl.
  • EXIF.
  • GD2.
  • Haru PDF functions.
  • htscanner.
  • Mcrypt.
  • Mimetypec.
  • MSSQL.
  • MySQL.
  • MySQLi.
  • OpenSSL.
  • PDO.
    • Firebird.
    • Microsoft SQL Server.
    • MySQL.
    • SQLite.
  • PHPDoc.
  • SMTP.
  • SOAP.
  • Sockets.
  • Standard PHP Library.
  • SQLite.
  • ssh2.
  • timezonedb.
  • uploadprogress.
  • zip.

Edite el archivo <ruta>\LightTPD\PHP\php.ini y active la variable cgi.fix_pathinfo removiendo el comentario (#).

cgi.fix_pathinfo=1

Creación de los scripts de inicio y parada.

Los scripts de inicio y parada utilizan RunHiddenConsole que es una herramienta para ocultar las consolas producidas durante la ejecución de php-cgi y de LightTPD. El archivo ejecutable RunHiddenConsole.exe se debe copiar en el directorio <ruta>\LightTPD.

Reemplazar <ruta> con la ubicación apropiada según la ruta donde se realizó la instalación anterior.

Script de inicio: _start.bat.

@ECHO OFF

SET RUTA=<ruta>\LightTPD

ECHO Starting PHP/FastCGI ...

%RUTA%\RunHiddenConsole.exe %RUTA%\PHP\php-cgi.exe -b 127.0.0.1:10000

ECHO Starting LightTPD...

%RUTA%\lighttpd.exe -f %RUTA%\conf\lighttpd-inc.conf -m lib

Script de parada: _stop.bat.

@ECHO OFF

SET RUTA=<ruta>\LightTPD

ECHO Stopping LightTPD ...

%RUTA%\bin\process.exe -k lighttpd.exe >nul

ECHO Stopping PHP/FastCGI ...

%RUTA%\bin\process.exe -k php-cgi.exe >nul

Prueba de funcionamiento.

En el directorio <ruta>\LightTPD\htdocs cree el archivo test.php con el siguiente contenido.

<?php

phpinfo ();

?>

Consultar la siguiente dirección utilizando un navegador web.

http://localhost/test.php

Si la configuración del servidor fue correcta deberá obtenerse una página similar a la siguiente.

Información de la configuración de PHP

Información de la configuración de PHP

Nótese como el campo Loaded Configuration File hace referencia a la ubicación precisa del archivo php.ini que se encuentra utilizando la instancia del servidor web. Esta información resulta muy útil a la hora de depurar problemas de configuración.

Recursos utilizados.

Después de realizar los procedimientos descritos anteriormente se obtienen la siguiente utilización de recursos de memoria.

  • LightTPD.exe - 1628KB.
  • php-cgi.exe - 8200KB.

Debe tenerse en cuenta que esta medida se realiza sin usuarios accediendo al sistema ni realizándose algún proceso, sin embargo es promisoria.

Enlaces:

Tags: , , ,

Cambio de locale y zona horaria en PHP

Desarrollo de software, Web November 28th, 2008

Una circunstancia muy común que se presenta en los servidores compartidos es que la zona horaria no corresponda con la del país o con la del usuario en general, esto repercute en el cálculo de la hora y la fecha actual.  Sucede algo similar con la información de localización.

Solucionar esto es muy sencillo, se deben incluír las siguientes instrucciones antes de realizar realizar cualquier invocación a estas instrucciones.

setlocale(LC_ALL, "es_CO");

putenv("TZ=America/Bogota");

El locale recibe información del idioma y el país.  Los códigos de los paises se pueden obtener del ISO639 y del ISO3166.

La variable de ambiente TZ recibe como parámetro la zona horaria.  El listado de zonas horarias puede consultarse en este enlace.

Tags:

Modelos en PHP: cosas buenas/malas del lenguaje

Desarrollo de software, Web October 15th, 2008

PHP es un lenguaje muy fácil de aprender si se tienen conocimientos en C/C++/Java/C# o similares.  Es muy fácil de utilizar y es muy fácil de desarrollar aplicaciones pequeñas-medianas con él.

También, como todo en la vida, tiene sus desventajas.  Lo interesante es que a mi parecer, las ventajas del lenguaje son también desventajas y viceversa según como se miren, es decir, según lo que se necesite.

En este momento me interesa mencionar dos de ellas:

  • Fuera de la caja de se obtiene lo básico, un lenguaje para empezar a escribir código, a diferencia de otros lenguajes que incluyen por si mismos todo un framework o ambiente de desarrollo.
  • Es un lenguaje señoritero, la falta de tipos y de la mucha rigurosidad de los demás lenguajes hace que hasta la gente que no sabe desarrollar software crea que si lo hace.

Estas son verdades: el lenguaje es deficiente para muchas cosas aunque les duelan a algunos que les gusta desgastarse simulando fanatismos hasta por un lenguaje de programación.  Pero como mencioné anteriormente, son cosas buenas/malas según como se les mire.

  • La independencia de tanta infraestructura que tal vez excede lo que necesitamos evita que las soluciones pequeñas y puntuales se conviertan en todo un circo de capas y niveles que consumen tiempo, recursos y paciencia.  Sería como utilizar JSF+Hibernate+Spring para hacer un HolaMundo.  Las soluciones son de la forma y el tamaño como el desarrollador las quiera: el problema es saber que querer y como lograrlo.De todos modos hay muchos frameworks para PHP allá afuera, desde los diminutos, los medianos y los grandes: MoonPHP, Picora, CodeIgniter, KohanaPHP, CakePHP, Prado, Symfony y Zend para nombrar a solo unos pocos del montón que existen en esta Internet que es tan larga como ancha.
  • Esta falta de rigurosidad bien utilizada, nos permite aprovecharla para hacer cosas cosas interesantes.  Todo es un arma peligrosa o una herramienta útil según quien la esté sosteniendo.

Y es con la flexibilidad que confiere la falta de rigurosidad la que permite o facilita la implementación -rápida- de códigos útiles.  MyModel 0.1 es solamente una demostración de las cosas que se pueden hacer con PHP y estoy seguro casi nadie conoce.

Los modelos son la representación de las clases de la lógica del negocio en una aplicación.  Algunos dicen que coinciden 1:1 con las entidades de persistencia: tablas de la base de datos.

Para los modelos, clases ellos con atributos y métodos, gracias al encapsulamiento acostumbramos a definir sus atributos como private/protected y a implementarles métodos setter/getter (obt/pon) para modificar o consultar su estado.

Este procedimiento trae consigo consecuencias negativas en medio de todo lo útil que es el encapsulamiento.

  • Hay que hacer métodos set/get para todos los atributos (que sea interesantes) de todas las clases de los modelos.
  • La mayoría de las veces hacemos unos métodos setter/getter que daría lo mismo que los atributos fueran public.
  • Es tedioso hacer los métodos, mas aún si como acabo de mencionar no incluyen siempre una ventaja tangible.  Los IDEs amables acostumbran a hacer por nosotros las plantillas básicas de estos métodos.

Este mes estuve pensando como poder hacer algo para solucionar estos problemas con PHP y recordé los métodos __set/ __get incluídos en toda clase PHP y se me ocurrió intentar implementar algo como las propiedades de .NET pero que funcionaran de manera automática.

Rápidamente implementé una primera versión que permite hacer esto.

Persona es una clase con un atributo llamado $nombre.  Si Persona hereda de MyModel estará entonces posibilitada para hacer esto:

$p -> Nombre = "Jorge";
echo $p -> Nombre;

La sobreescritura de los métodos mencionados antes me permiten decirle al modelo que cuando le hablen de la propiedad Nombre haga referencia al atributo nombre.  Mas aún, cuando le hablen de Nombre primero verifique si existen los métodos setNombre y getNombre y haga uso de ellos.

Una segunda mini versión le agregó un poco mas de encapsulamiento.

  • Si el atributo es private, no se puede acceder de ninguna manera.
  • Si el atributo es protected sólo se puede acceder desde el exterior si tiene setter/getter.
  • Si el atributo es public se puede acceder externamente.
  • Si el atributo es public pero tiene setter/getter, estos métodos serán utilizados en lugar del acceso directo.
  • Sólo las propiedades cuyos métodos setter/getter sean public pueden ser accedidas desde el exterior.

Con esto podemos hacer, digo yo, los modelos con atributos public y filtrar con métodos setter/getter los que nos interese restringir su acceso.

Ejemplo:

Téngase en cuenta a la clase User cuya implementación es de la siguiente manera.

class User extends MyModel
{
    private   $id;
    public    $username;
    public    $password;
    protected $name;
 
    public function getPassword()
    {
        return str_repeat("*", strlen($this -> password));
    }
 
    public function setName($value)
    {
        $this -> name = "--- " . $value . " ---";
    }
 
    public function getName()
    {
        return strtoupper($this -> name);
    }
}

Considérese un programa que la utiliza como se muestra a continuación.

$u = new User();
 
// $u -> id = 7;                               // Inválido porque $id es private y no ha métodos set/get.
 
$u -> Username = 'jimezam';                  // Se accede directamente porque $username es público.
echo "username: " . $u -> Username . "";     // Se accede directamente porque $username es público.
 
$u -> Password = 'secreto';                   // Se accede directamente porque $password es público.
echo "password: " . $u -> Password . "";     // Se ejecuta getPassword.
 
$u -> Name = "Jorge Ivan";                   // Se ejecuta setName.
echo "nombre: " . $u -> Name . "";           // Se ejecuta getName.

El resultado es el siguiente por los motivos explicados en los comentarios frente a cada línea del código.

username: jimezam
password: *******
nombre: --- JORGE IVAN ---

Se aceptan sugerencias constructivas para ir complementando a MyModel.

Enlaces:

Tags:

10 principles of the PHP masters

Desarrollo de software, Web October 5th, 2008

Esta semana volví a toparme con este artículo en nettuts.com, es interesante y vale la pena hacer referencia a él.  Fue escrito por Glen Stansberry quien también ha escrito otros artículos similares como los mencionados a continuación.

En este artículo el autor compila 10 principios o sugerencias para obtener un mayor provecho del desarrollo con PHP incluyendo a su correspondiente explicación desde el punto de vista del autor que los sugiere.

Los puntos tratados hacen referencia a los siguientes temas.

  1. Use PHP Only When You Need it
  2. Use Many Tables With PHP and MYSQL for Scalability
  3. Never, ever trust your users
  4. Invest in PHP Caching
  5. Speed up PHP Development with an IDE, Templates and Snippets
  6. Make Better Use of PHP's Filter Functions
  7. Use a PHP Framework
  8. Don't use a PHP Framework
  9. Use Batch Processing
  10. Turn on Error Reporting Immediately

Enlace: 10 Principles of the PHP Masters.

Tags: ,

Transacciones de base de datos con Kohana

Desarrollo de software, Móvil, Software, Web September 25th, 2008

Aparentemente la versión actual de Kohana (2.2) aún no cuenta con soporte para transacciones en su clase Database.

Buscando entre los foros encontré una solución sencilla, rápida y elegante, sin embargo me preocupa que, a pesar de que utiliza la sintaxis de CodeIgniter, no vaya a ser compatible con la siguiente liberación de Kohana de la cual no encontré documentación.

Así que por ahora voy a establecer las transacciones de manera manual y -espero- compatible con las bases de datos y futuras liberaciones de Kohana.

Iniciar la transacción.

$this -> db -> query('SET AUTOCOMMIT=0');
$this -> db -> query('BEGIN');

Aceptar/ejecutar la transacción.

$this -> db -> query('COMMIT');
$this -> db -> query('SET AUTOCOMMIT=1');

Cancelar/devolver la transacción.

$this -> db -> query('ROLLBACK');
$this -> db -> query('SET AUTOCOMMIT=1');

Nota: para Microsoft SQL Server los comandos deberán ser BEGIN TRANSACTION, COMMIT TRANSACTION y ROLLBACK TRANSACTION. Las modificaciones al AUTOCOMMIT no son válidas para este motor de base de datos.

Enlaces:

Tags: , , ,

Utilizar phpDoc en Ubuntu

Desarrollo de software, Web September 8th, 2008

Descargar la última distribución de phpDocumentor del sitio oficial.

Descomprimir el paquete recién descargado en la ubicación de destino.

$ unzip PhpDocumentor-1.4.2.zip

Instalar el intérprete de PHP desde línea de comando si no se tiene aún.

$ sudo apt-get install php5-cli

Crear el script de ejecución.

$ vi run.sh

PHP_CLI=`which php`
TYPE=HTML
DOCUMENTOR_PATH=/$HOME/PhpDocumentor
PHP_INI=/etc/php5/cli/php.ini
SOURCE_PATH=$1
DESTINATION_PATH=$2
TITLE=$3
PARSEPRIVATE=$4
export PHP_CLI PHP_INI TYPE DOCUMENTOR_PATH
export SOURCE_PATH DESTINATION_PATH TITLE

$PHP_CLI "-c $PHP_INI" "$DOCUMENTOR_PATH/phpdoc" -t $DESTINATION_PATH -o $TYPE:frames:default -d $SOURCE_PATH --title $TITLE --parseprivate $PARSEPRIVATE --quiet

Tenga en cuenta personalizar el contenido de las variables DOCUMENTOR_PATH (ubicación donde se instaló el phpDoc) y TYPE (tipo de formato generado) el cual puede ser HTML, PDF, XML o CHM.

Actualizar los permisos de ejecución del script.

$ chmod +x run.sh

$ chmod +x phpdoc

Ejecutar el script de generación de documentos.

$ $HOME/PhpDocumentor/run.sh UBICACION_ORIGEN UBICACION_DESTINO TITULO INCLUYE_PRIVADO

Tenga en cuenta el significado de las siguientes variables en la ejecución del comando anterior.

  • UBICACION_ORIGEN: directorio base que contiene los archivos fuente de los cuales se generará la documentación.
  • UBICACION_DESTINO: directorio donde se almacenará la documentación generada.
  • TITULO: título de la documentación a generarse.
  • INCLUYE_PRIVADO: indicación para incluír (on) o no incluír (off) la información privada (@internal) en la documentación generada.

Ejemplo:

$ $HOME/PhpDocumentor/run.sh /web/proyecto/ $HOME/doc "Documentación del proyecto" on

El comando anterior genera la documentación del código fuente ubicado bajo /web/proyecto/ y lo almacena en $HOME/doc, incluyendo la información de las etiquetas privadas (on) y con el texto "Documentación del proyecto" como título.

Enlaces:

Tags: ,

Modelos bajo subdirectorios en Kohana

Desarrollo de software, Web August 25th, 2008

Después de desarrollar dos proyectos utilizando CodeIgniter decidí para los nuevos proyectos utilizar Kohana el cual hasta ahora ha sido un cambio agradable desde el punto de vista de una mejor orientación a objetos y el soporte de una comunidad mas dinámica.

Debido a que CI y por supuesto Kohana que es un fork de la primera, separan a las entidades del MVC en directorios por separado: /controllers, /models y /views, me he acostumbrado a crear subdirectorios dentro de ellas para separar los objetos de cada uno de los módulos que componen al sistema de información.  Ejemplo: /controllers/admin/perfil.php.

Con CI cargaba los modelos utilizando la siguiente sintáxis:

    $this -> load -> model("admin/perfil");

Ahora con Kohana esta sintáxis es obsolota y deben instanciarse los objetos, ya sea con un ámbito local:

    $perfil = new Perfil_Model();

O con un ámbito global a todo el controlador.

    $this -> perfil = new Perfil_Model();

El problema es que ya no hay forma de especificar el subdirectorio del módulo (no confundir con los módulos de Kohana) que para hechos prácticos de la instanciación del modelo es una cadena de texto.

Estuve revisando la documentación y los foros de Kohana y al parecer aún no hay una solución nativa a esta situación, así que decidí implementar la mia propia que permita la carga modelos en subdirectorios desde cualquier controlador y que hasta la fecha me ha funcionado bien.

Para la implementación de la autenticación que me dispongo a realizar próximamente he definido mi propio controlador base definiendo la clase Controller en application/libraries/MY_Controller.php.  Con esto defino los comportamientos generales que tendrán todos los controladores del proyecto.

<?php defined('SYSPATH') or die('No direct script access.');
 
class Controller extends Controller_Core
{
    public function __construct()
    {
        parent::__construct();
    }
}
 
?>

A este controlador base le agrego los métodos necesarios para localizar el archivo .php que contiene el modelo que se intenta instanciar y realizo las modificaciones necesarias para incluír esta búsqueda durante la etapa de autocarga de clases (autoload).  Los nombres del módulo (del SI), controlador, acción y parámetros son obtenidos en tiempo de ejecución gracias a la facilidad de la clase Router.

El primer método a implementarse es buscarArchivo($directorio, $archivo) el cual se encarga de realizar la búsqueda física y recursiva de $archivo dentro del $directorio especificado.

Se implementa al método auto_load($clase) el cual determina si la clase a cargarse es un modelo debido a la terminación _Model de su nombre de clase, por ahora ignora cualquier otro tipo.  En caso de ser un modelo realiza la búsqueda utilizando al método definido anteriormente, el cual en caso de encontrarlo lo incluye para hacerlo disponible al ambiente de ejecución.

Como paso final, en el constructor del Controller se le indica que tome al método auto_load como una de las funciones ejecutadas durante la autocarga de clases.

    spl_autoload_register(array('Controller', 'auto_load'));

Gracias a estas modificaciones es posible realizar la creación del objeto new Perfil_Model y el controlador se encargará de realizar la búsqueda y encontrarlo dentro del subdirectorio /models/admin.  Sobra hacer notar que para esta solución, la colisión de nombres es un problema ya que se resuelve según sea la clase que se encuentra físicamente primero en el directorio de archivos.

El código fuente del ejemplo descrito puede descargarse del siguiente enlace: MY_Controller.php.

Tags: ,

Introducción a Kohana Framework

Desarrollo de software, Web July 25th, 2008

KohanaPHP  es  un  framework  liviano  y  flexible  para  el desarrollo  de  aplicaciones  web  pequeñas  y  medianas con PHP.   Se basa  en CodeIgniter  al cual complementa con  una  mejor  apropiación  de  la  OO  y  PHP5,  así  como un mayor soporte brindado por toda una comunidad.

En  esta  sesión  se  expondrán  los  conceptos  del framework  necesarios  para  empezar  a  diseñar  las aplicaciones  web,  sin  embargo  no  se  profundizarán  en detalles  específicos,  se  recomienda complementar  este documento  junto  con  el  wiki  de  la  sección  de documentación.

 
  • Introducción.
  • Características.
  • Instalación.
  • Directorios.
  • Configuración.
  • URLs.
  • Controladores.
  • Librerías.
  • Ayudantes.
  • Vistas.
  • Modelos.
  • Eventos.
  • Hooks.
  • Manejo de errores.
  • Módulos.
  • Recursos del framework.

Tags: , ,

Configurando Apache 2.2.x/PHP 5.2.x con FastCGI mod_fcgid en FreeBSD 7.x

Linux/Unix/FreeBSD May 26th, 2008

Descargar compilar e instalar el paquete mod_fcgid y sus posibles dependencias.

# cd /usr/ports/www/mod_fcgid
# make install clean

Verificar que la instalación de PHP cuente con el soporte de FastCGI.

# /usr/local/bin/php-cgi -v

Configurar a Apache para que utilice el nuevo módulo de FCGI.

# vi /usr/local/etc/apache22/httpd.conf

Agregar al final del archivo httpd.conf.

LoadModule fcgid_module libexec/apache22/mod_fcgid.so

<IfModule mod_fcgid.c>
    AddHandler fcgid-script .fcgi
    FCGIWrapper /usr/local/bin/php-cgi .php
</IfModule>

Ubicar la sección del directorio del DOCUMENT_ROOT y complementarla con la nueva opción.

<Directory "/home/web">
    # ...
    Options ExecCGI
</Directory>

Reiniciar el servicio de Apache para que se tengan en cuenta los cambios realizados.

# /usr/local/etc/rc.d/apache22 restart

Consultar la salida de phpinfo() para verificar su correcto funcionamiento.

Tags: , ,

“phpinfo” en Wordpress

Internet, Software, Web May 20th, 2008

Acabo de darme cuenta de algo interesante. A este Wordpress (2.5.1) no le gusta del todo la palabra phpinfo. Si la escribo en un post o en una página junto con dos paréntesis de parámetros sin espacio que los separe me muestra siempre un error 503.

Esta línea de texto.

Produce este error cuando deseo guardar o publicar el mensaje.

Nótese que el texto hace parte del contenido del post, es decir la idea es que se muestre tal cual, no que sea interpretado por PHP.

Extrañamente si agrego un espacio entre la función y los parámetros de esta forma.

Funciona de maravillas.  Aunque usted ... no lo crea ;-)

Tags: ,