Archivos para las entradas con etiqueta: php

El motivo de este post es para presentar una clase que ayuda al procesamiento de formularios en PHP (también estará la versión Java) teniendo en cuenta su facilidad de uso (como jQuery Validate).

Para descargarlo acá tienen el desarrollo (y el ejemplo): FormValidate.

Configuración

Para tener una forma de hacer cambios rápidos sin tener que hacer modificaciones en el código se usa un archivo ini, en la que para cada campo a considerar se define una sección y sus atributos a validar, por ejemplo:

;ESTE ARCHIVO ES UN EJEMPLO PARA PHPTools -> FomrValidate

;Campo para evitar los robots
[f0]
type=security

;Campo de tipo númerico
[f1]
type=number
min=5
required=true

;Campo de tipo mail
[f2]
type=mail

;Campo que requiere una expresión regular
[f3]
type=regex
regexstr="/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/i"
max=100
required=true

;Campo con un tamaño mínimo de 20 caracteres
[f4]
min=20

donde:

  • f0: se usa para evitar robots, si el campo llega con información, se debe desechar la información.
  • f1: se valida que sea un número mayor o igual a 5 y siempre debe tener información.
  • f2: se valida que sea un correo electrónico válido.
  • f3: se valida que cumpla con la expresión regular (regexstr) usando la función PHP preg_match, con un máximo de 100 caracteres y siempre debe tener información.
  • f4: se valida que el tamaño mínimo sea de 20 caracteres.

Uso

Ahora para poder validar los datos enviados al servidor, vamos a hacer uso de este script:

<?php
include "PHPTools/FormValidate.php";

$form = new FormValidate(array(
                'get' => true,
                'path' => 'properties',
                'ini' => 'form'
));
// limpiar entrada
$form->escape();
// validar
$form->validate();
?>

En la descarga de FormValidate el ejemplo muestra el arreglo antes de ser validado y después (que agrega mensajes de error y llena el arreglo de errores en caso de existir).

Especificaciones

Estos son los valores de los parámetros usados para la configuración:

  • required: determina si el campo es necesario.
  • type: especifica como se tiene que validar el dato. Sólo se pueden usar security, number, mail y regex.
  • max: Tamaño/valor máximo del campo; si es number se compara directamente, en otro caso se compara el tamaño de la cadena.
  • min: Tamaño/valor mínimodel campo; si es number se compara directamente, en otro caso se compara el tamaño de la cadena.
  • regexstr: Cadena con la expresión regular (se usa la función preg_match), debe de ir entre comillas.

Estos son los valores de los parámetros para  el uso de la clase FormValidate

  • get: con el valor true determina si se va a procesar los valores de $_GET, si no se define usa los valores de $_POST
  • path: determina el path donde se encuentra el archivo ini
  • ini: el nombre del archivo ini. También se puede definir un array con las propiedades y así evitar el uso del archivo ini.

TODO

Estas son algúnas tareas que faltan en este desarrollo:

  • Agregar tipos de datos especiales (por ejemplo: fecha).
  • Cambiar el parámetro para la clase FormValidate para usar $_GET.
  • Hacer más flexible el sistema de mensajes de error.
  • Dependencia entre campos.

Licencia

Este clase tiene la licencia MIT.

Este artículo se basa en mi experiencia en el trabajo, desarrollo de aplicaciones web, y de llevar a estas el requerimiento no funcional del rendimiento del navegador al momento de hacer el render de la página. Para poder medir este requerimiento use la herramienta web GTmetrix que realiza dos pruebas (YSlow y Page Speed) de la página web a mostrar.

Hasta este momento parte de mi trabajo ha sido trabajar con el CMS modx, que pesar de tener una nueva versión llamada revolution (con muchas mejoras sobre la versión anterior), sigue con el problema de manejar el código (html o php) a través de la base de datos y dificultando su manejo a través de su administrador. Para paliar este problema, y mostrar las maravillas de automatizar tareas, realize una clase en Java para interactuar entre archivos físicos (de tu ambiente de desarrollo) y la base de datos con el código de estos (sin tener que abrir el administrador de modx).

(Algunas) herramientas para automatizar

Para automatizar tenemos muchas herramientas que permiten hacerlo, como por ejemplo, scripts de shell o archivos de procesos por lotes. Debido a que son herramientas que cubren necesidades diferentes preferí no apegarme a una de estas opciones, en cambio, dada la extensión del lenguaje Java y las herramientas basadas en este lenguaje que permiten automatizar tareas en el desarrollo decidí usar Apache Ant.

Si buscas compresores para CSS o Javascript hay muchos online, que desde mi punto de vista son buenos para hacer el proceso una sola vez. Sin embargo, si deseas integrar esta actividad de manera continua en tus proyectos creo que verás que no es ameno estar desarrollando en x programa, abrirlo, copiar el contenido del archivo, pegarlo en el navegador y poner el resultado en un nuevo archivo. Por este motivo para la compresión de las hojas de estilos y archivos javascript he usado YUI Compressor que es una clase Java y que se puede ejecutar desde línea de comandos. Para la compresión de HTML use la herramienta HTML Compressor que básicamente cambia los saltos de línea y tabuladores en espacios en blanco.

Para el manejo de los elementos de modx hice una clase en Java (para ejecutar desde la línea de comandos) y evitar trabajar con estos a través del navegador (dejando la tarea del desarrollo a herramientas hechas para esto). Al desarrollo lo llame modxConnect y la idea es que una vez que se encuentra comprimidos los elementos (html) modxConnect inserte el contenido de los elementos en la base de datos de modx. Falta mucho desarrollo, pero es un primer acercamiento.

Para los siguientes pasos supongo que ya esta configurado todo este ambiente:

  • Java (si ya esta configurado el acceso al classpath mejor)
  • Apache Ant que este accesible desde línea de comandos (lo puedes agregar al classpath) y si no pues tienes que poner la ruta completa del ejecutable (en Apache Ant User Manual puedes encontrar como instalarlo y empezar a usarlo).
  • YIU Compressor, HTML Compressor y modxConnect accesibles a través de la línea de comandos (o configurando el archivo de Apache Ant para determinar la ruta de donde se encuentran).

Ahora ya que tienes listo este ambiente de desarrollo vamos a empezar la configuración para la automatización.

Configurar

Uno de los beneficios de Apache Ant, es que solo tienes que crear un archivo XML llamado build.xml (por lo general, pero puedes hacer referencia a otro archivo) y es donde definirás las tareas (targets) repetitivas que deseas realizar de manera automática. La estructura básica del archivo build.xml es:

<?xml version="1.0" encoding="UTF-8"?>
<project name="NombreProjecto" default="clean" basedir=".">
	<property file="build.properties" />
	<target name="clean" depends="" description="">
		<delete dir="${build}" />
		<delete dir="${dist}" />
	</target>
	<target name="clean" depends="" description="">
		<delete dir="${build}" />
		<delete dir="${dist}" />
	</target>
</project>

Ahora comentemos un poco de las etiquetas (que puedes ver más a detalle en Apache Ant User Manual):

  • project: se usa para definir información al proyecto. El atributo name es para asociarle un nombre, default es la tarea (target) que se ejecutará por default y basedir para asociar el directorio sobre el que se estará trabajando.
  • property: se usa para asociar “variables” al archivo build.xml, puedes ponerlas directamente o asociar un archivo properties con los valores, a los que haces referencia con los placeholders ${nombreVariable}.
  • target: es la definición de una tarea que realizará. El atributo name es el nombre de esta (y como será llamada por Ant), depends es la lista de tareas que deben completarse antes de llevar a cabo la tarea seleccionada y description es una descripción de la tarea.

Antes de continuar, necesitamos la información del archivo build.properties:

dir.src=src
dir.build=build
dir.sub=assets
dir.js=js
dir.css=css
dir.server=C:/servers/xampp/htdocs/app
dir.chunks=chunks
dir.lib=lib
dir.classPHP=class
dir.processPHP=process
dir.propertiesPHP=properties
dir.modx=C:/servers/xampp/htdocs/cmsModx
dir.ftp=urlFTP
server.dir=00.000.00.00
server.usr=usuario
server.pwd=password
file.css=style.css
file.js=scripts.js
file.chunk.css=html.css.xhtml
file.chunk.js=html.js.xhtml
dir.compressor=C:/tools/yuicompressor-2.4.2/build
class.compressor=yuicompressor-2.4.2.jar
dir.compressorHTML=C:/tools/htmlcompressor
class.compressorHTML=htmlcompressor-0.9.1.jar

Y ya que se definió una tarea, para realizarla necesitas llamar a ant y darle el nombre de la tarea como parámetro:

ant nombreTarget

Una de las primeras tareas, y practicas en Java, es tener por separado el ambiente de desarrollo y el ambiente de producción, que por lo general es la compilación de los fuentes, pero en este caso solo será los archivos fuentes con cierto proceso (compresión) y para llevar a cabo esta tarea, se puede definir una tarea como la que sigue:

<target name="makeDirs" description="Crea los directorios sobre los que se trabajara">
	<copy todir="${dir.build}">
		<fileset dir="${dir.src}">
			<exclude name="**/*.*" />
			<exclude name="**/js/src/**" />
		</fileset>
	</copy>
</target>
  • copy: copia los archivos/directorios a donde se indique todir.
  • fileset: define, a través de dir, los archivos que serán copiados.
  • exclude: define la referencia de los archivos que no deben ser copiados a todir, se pueden usar comodines (** significa que no importa la carpeta)

Para este caso solo se crea la estructura de directorios (como lo tengas en desarrollo) ya que en otras tareas se harán los procesos para comprimir los diferentes tipos de archivos. Puedes permitir copiar las clases PHP o las imágenes desde un principio (aunque más adelante puedo dar unas ideas para no hacerlo aún).

Empecemos a hacer una de las tareas repetitivas: comprimir CSS y JS. Si se dificulta tener una sóla hoja de estilos (siempre es más ordenado separar los estilos de las secciones en diferentes archivos) entonces primero juntemos toda la información de las hojas de estilos en un sólo archivo (lo mismo pasa con los archivos de los javascripts), para eso se pueden hacer unas tareas como estas:

<target name="conCSS" description="Concatena los CSS a un archivo en el directorio BUILD">
	<concat destfile="${dir.build}/${dir.sub}/${dir.css}/${file.css}" force="no">
		<filelist dir="${dir.src}/${dir.sub}">
			<file name="${dir.css}/charset.css" />
			<file name="${dir.css}/reset.css" />
			<file name="${dir.css}/estilo1.css" />
			<file name="${dir.css}/estilo2.css" />
			<file name="${dir.css}/estilo3.css" />
		</filelist>
	</concat>
</target>
<target name="conJS" description="Concatena los JS a un archivo en el directorio BUILD">
	<concat destfile="${dir.build}/${dir.sub}/${dir.js}/${file.js}" force="no">
		<filelist dir="${dir.src}/${dir.sub}">
			<file name="${dir.js}/jquery-1.4.2.js" />
			<file name="${dir.js}/jquery.ui.core.js" />
			<file name="${dir.js}/jquery.ui.widget.js" />
			<file name="${dir.js}/jquery.ui.mouse.js" />
			<file name="${dir.js}/jquery.ui.draggable.js" />
			<!-- wrapper > -->
			<file name="${dir.js}/wrapStart.js" />
			<file name="${dir.js}/main1.js" />
			<file name="${dir.js}/main2.js" />
			<file name="${dir.js}/main3.js" />
			<file name="${dir.js}/wrapEnd.js" />
			<!-- < wrapper -->
		</filelist>
	</concat>
</target>
  • concat: con esta tarea concatenas los archivos (de filelist) en el path/archivo definido en destfile.
  • filelist: define los archivos que serán concatenados. Si agregas uno más Ant automáticamente lo incluirá en el archivo final.
  • En la tarea de la compresión de los javascript puse dos archivos para crear el template de carga de las acciones de jQuery, donde $document.ready(function() { esta en  wrapStart.js mientras que en wrapEnd.js se encuentra });

Comprimir los archivos de CSS y JS ya concatenados (con el YUI Compressor):

<target name="compressCSS" description="comprime el CSS de BUILD" depends="conCSS">
	<exec executable="cmd">
		<arg line="/c java -jar ${dir.compressor}/${class.compressor} ${dir.build}/${dir.sub}/${dir.css}/${file.css} -o ${dir.build}/${dir.sub}/${dir.css}/${file.css} " />
	</exec>
</target>

<target name="compressJS" description="comprime el js de BUILD" depends="conJS">
	<exec executable="cmd">
		<arg line="/c java -jar ${dir.compressor}/${class.compressor} ${dir.build}/${dir.sub}/${dir.js}/${file.js} -o ${dir.build}/${dir.sub}/${dir.js}/${file.js} " />
	</exec>
</target>
  • exec: establece que se usará una instrucción de línea de comando.
  • arg: es propiamente la llamada a la instrucción para comprimir el archivo.

Con esto ejecuta

ant compressJS compressCSS

y siempre se generarán los archivos de JS y CSS comprimidos.

Los archivos HTML y PHP son muchos y no tiene caso que los concatenemos, pero si se puede “comprimir” (eliminar los metacaracteres) para agilizar la transferencia de los archivos. Esto se resuelve con la siguiente tarea:

<target name="compressAll" depends="makeDirs">
	<apply executable="java" parallel="false">
		<fileset dir="${dir.src}/" includes="**/*.html,**/*.php,**/*.xhtml">
			<exclude name="**/config/**" />
			<exclude name="**/css/**" />
			<exclude name="**/js/**" />
			<exclude name="**/lib/**" />
			<exclude name="pagina1.php" />
			<exclude name="pagina2.php" />
			<exclude name="pagina3.php" />
		</fileset>
		<arg value="-jar"/>
		<arg path="${dir.compressorHTML}/${class.compressorHTML}"/>
		<arg line="--type html"/>
		<srcfile/>
		<arg value="-o"/>
		<mapper type="glob" from="*" to="${dir.build}/*"/>
		<targetfile/>
	</apply>
	<copy todir="${dir.build}/${dir.sub}/${dir.lib}">
		<fileset dir="${dir.src}/${dir.sub}/${dir.lib}" includes="**/*.php"></fileset>
	</copy>
</target>
  • apply: es otra forma de ejecutar un comando (en línea de comandos) aplicado a los archivos definidos por fileset.
  • fileset: conjunto de archivos que serán comprimidos. En includes se seleccionan todos los archivos HTML, PHP y XHTML, excepto pagina1.php, pagina2.php y pagina3.php.
  • arg: argumentos para la llamada de la línea de comandos.
  • srcfile: referencia al archivo de fileset.
  • mapper: define la salida del archivo.
  • Al final copia todos los archivos excluidos (clases de PHP) a la carpeta build.

Por último resolvemos el inconveniente de modx respecto a los elementos con modxConnect. La definición de la tarea:

<target name="copyServer" depends="compressJS,compressCSS,compressAll">
	<exec executable="cmd">
		<arg line="/c C:\Java\jdk1.6.0_03/bin/java -jar C:\tool\modxConnect.jar" />
	</exec>
	<!-- limpiar el cache del modx -->
	<exec executable="cmd">
		<arg line="/c curl http://SITEURE/clearCache.html" />
	</exec>
</target>
  • El primer comando es para llamar a la clase que hace el mapeo (modxConnect). Como se encuentra no es funcional (por la configuración que se encuentra en los archivos properties del jar). Para poder usarlo tienes que configurar la base de datos, los paths donde se encontrarán los archivos (ya comprimidos) y crear los chunks a través del modx y después ligar el archivo físico con el id del chunk (en los archivos properties vienen comentarios al respecto).
  • El segundo comando es para limpiar la cache del modx. Se necesita definir un documento y asociarle el snippet con el código siguiente:
<?php
// Snippet para limpiar la cache
$paths = array(
	'config.cache.php',
	'sitePublishing.idx.php',
	'registry/mgr/workspace/',
	'lexicon/'
);
$contexts = $modx->getCollection('modContext');
foreach ($contexts as $context) {
	$paths[] = $context->get('key') . '/';
}
$options = array(
	'publishing' => 1,
	'extensions' => array('.cache.php', '.msg.php', '.tpl.php'),
);
if ($modx->getOption('cache_db')) $options['objects'] = '*';
	$results= $modx->cacheManager->clearCache($paths, $options);
return 'OK';
?>

Ya configuraste todo, pero no te olvides de agregar una tarea que borre todo lo que generaste

<target name="clean" description="limpiar los paths">
	<delete dir="${dir.build}" />
	<delete dir="${dir.server}" />
</target>

Que lo haga la computadora

La parte más sencilla de esto: usar Apache Ant. Una de las ventajas de modularizar la construcción, es que puedes hacer cualquier paso intermedio y no tener siempre que ejecutar todo, por esa razón se separo la concatenación de los archivos de la compresión o la creación de el árbol de producción.

Para ejecutar todas las tareas, ponemos

ant compressAll

Por ejemplo, esta modificando la hoja de estilos y solo quieres concatenar los archivos (sin comprimir) sólo ejecutas

ant compressCSS

y ya solo subes el archivo y haces el debug (lo mismo se puede hacer con los javascript).

Conclusiones

Este artículo se centra en mejorar algunos procesos en el desarrollo de software. Después de estar trabajando un tiempo de esta manera mi experiencia me dice que HAY QUE ORGANIZAR LOS PROYECTOS (y esto incluye como se implementará) para atender procesos que son susceptibles de automatizar y mejorar la calidad en este rubro.

También es dar algunas ideas respecto a lo que se me ocurre automatizar:

  • Esteganografía: crear procesos que oculten datos dentro de imágenes (el uso más sencillo que he visto al respecto) como inyectar claves en ciertas imagenes del sitio web.
  • FTP: subir cierta parte del desarrollo (como las imágenes) sin tener que abrir el programa FTP.
  • Ambientes de desarrollo: generar la estructura general de los proyectos siempre que se inicie (sin estar apegado a un IDE).
  • Criptografía: hacer procesos para encriptar información (en la base de datos o en archivos).
  • Desarrollo: puedes poner códigos que midan el tiempo de cierta sección (consulta a la base de datos por ejemplo) y que en la aplicación final no necesitas.

Después de un pequeño rato de luto, he regresado para seguir quejandome de todo lo que se me ocurra, pero mientras encuentro de que quejarme (el aumento a la gasolina, tortillas, cerveza, etc.) voy a poner un poco de XML para explicar como crear una página web modular (con PHP) leyendo el archivo XML de configuración de la página (esto será por partes).

Me baso en este artículo, con la diferencia de que yo voy a usar un archivo XML con el listado (y configuración) de las ‘páginas’ proporcionadas por la aplicación. Antes de empezar quiero exponer el por qué usare un archivo XML para la configuración en vez de las variables PHP. La primera vez que leí el artículo se me hizo raro, sobre todo porque apenas empezaba a conocer PHP (a estas alturas no sé mucho), depués de algunos intentos le empece a entender, pero el hecho de diseñar la presentación (hojas de estilo) separada de la lógica me hacía muy difícil encontra una manera ordenada de acomodar los datos de x página en una variable (mas bien arreglo) de PHP. A XML lo metí porque una vez que uno estudia acerca de este lenguaje se le hace fácil hacer diseñós de estructuras (no son los mejores porque a uno le falta experiencia) y a mí se me hizo mas intuitivo, aunque hay un poco de problemas porque tenemos que usar librerías para XML (yo usaré DOM), pero no hay problema si uno se anima un poco para esto.

Antes de empezar les quiero recomendar los siguientes programas para desarrollar esto: si no sabes instalar Apache con PHP usa XAMPP, lo que me gusta de este es que no necesita ser instalado (puede correr desde una memoria USB), ya viene configurado PHP (con lo necesario para este ejemplo), hasta MySQL (aunque preferíria PostgreSQL u Oracle) y la verdad tener un servidor web corriendo en tu máquina tiene su gasto de recursos y no siempre estoy programando sobre web. Como esto no va a ser de diseñó gráfico web nos vamos a olvidar de Dreamweaver y usaremos un editor de texto, pero no cualquiera, les recomiendo Notepad++. No necesitas estos programas forzosamente, pero a mí se me han hecho muy comodos y como es básico esto no necesitaremos un IDE para PHP.

Todo en este mundo necesita diseño. Una que hay que entender (desde mi punto de vista) es que una página dinámica se compone de scripts (programas) en el servidor y si quieres scripts en el cliente, la presentación (en el cliente) con hojas de estilo (por ser mas fácil de manejar). Bajo estas ideas desarrolle este archivo XML que contiene el listado de una ‘página’ (ver 1):<?xml version=”1.0″ encoding=”iso-8859-1″?>
<configuration page=”nombre_seccion”>

<scripts>
<client>
<li type=”file”>archivo.js</li>
</client>
<server>
<li type=”file”>archivo.php</li>
</server>
</scripts>
<design>
<li>archivo_estilo.css</li>
</design>
<modules struct=”archivo_base_maquetacion”>
<li div=”destino”>archivo_modulo.ext</li>
</modules>

</configuration>

Uno de los problemas es que vas a un XML por cada’página’ de tu web, podrías meter varias descripciones de ‘página’ en cada XML, pero en este caso el problema es que se usa DOM para leer el XML y esto consume recursos. Mi sugerencia es el que sigue:

<?xml version=”1.0″ encoding=”iso-8859-1″?>
<configuration section=”nombre_seccion”>

<libs>
<scripts>
<client>
<li type=”file”>archivo.js</li>
</client>
<server>
<li type=”file”>archivo.php</li>
</server>
</scripts>
<design>
<li>archivo_estilo.css</li>
</design>
<modules struct=”archivo_base_maquetacion”>
<li div=”destino”>archivo_modulo.ext</li>
</modules>
</libs>

<page name=”nombre_pagina”>
<scripts>
<client>
<li type=”file”>archivo.js</li>
</client>
<server>
<li type=”file”>archivo.php</li>
</server>
</scripts>
<design>
<li>archivo_estilo.css</li>
</design>
<modules struct=”archivo_base_maquetacion”>
<li div=”destino”>archivo_modulo.ext</li>
</modules>
</page>

</configuration>

¿Por qué mas complejo? Porque pienso que una carpeta con una aplicación web usara librerías generales (que esta en la etiqueta <libs>) y varías ‘subpáginas’, pero como no quiero verme muy complicado usaremos la primera versión para desarrollar este ejemplo.

Por el momento es todo, pero el siguiente post pondre el schema (la definición de datos del archivo XML de configuración) y empezare a hablar de PHP y XML (DOM). Pronto pondre los archivos en algún lugar para que puedan descargarlos (porque en este CMS no puedo indentar el código)

Pues la persona que lo puso es uno de mis amigos de la UAM y pues sus comentarios son atinados, pero esa vez escribí por desesperación, creo que haber ido al D.F. me estreso y mi familia lo pago, aunque ya se me paso.

Pues estoy frustrado porque no puedo configurar PHP en IIS, dado que puedo configurarlo para usar el famoso phpinfo() y sale como si nada, pero a la hora de tratar de usar comandos de MySQL esta cosa dice que no carga las librerias, y pues le he movido al maldito php.ini y nada. Ya me han comentado que use AppServ, pero la verdad quiero hacerlo con IIS (soy terco para eso) ya que puedo usar ASP.NET (auqneu con Mono Apache tiene posibilidad de manejar ASP.NET). Como sea, volvere a intentarlo.

Otra queja: Esta cosa esta muy lenta (bitacoras.com), y pues en los anuncios dicen que para el fin de semana va a dejar de haber acceso a las bitacoras por un tiempo (horas hacen referencias en el anuncio), como sea no escribo a diario. Estoy en el trabajo de mi mamá y pues logre hacer un encabezado que me me gusto (con PhotoShop) y no puedo verlo en la máquina de mi mamá (no se porque algunas imagenes en jpg si se ven en el navegador y la que hice no).

Adióx.

Y lo mas díficil fue configurar IIS y PHP porque no leía las instrucciones y pensaba que ya sabía, pero, ¡oh! sorpresa, me faltaban muchas cosas que configurar (ya que no solo es instalar). Pero casi acabando las vacaciones pude configurarlo, pero después llego mi coco de no poder configurar MySQL y no podía hacer consultas a una base de datos, no se que hice pero al final pude lograr hacer consultas, ahora solo falta la parte fuerte: lograr modificar la base de datos, pero creo que leyendo los comandos de PHP se puede hacer facil (eso creo).

Adiox.