Componentes y helpers en cakephp

Tanto los componentes como los helpers están diseñados para extender las funcionalidades que el propio núcleo cake nos ofrece. La diferencia? bien sencilla. Mientras los componentes añaden lógica de negocio a nuestro proyecto, los helpers añaden lógica de presentación.

Componentes:
Existen multitud de componentes que podemos descargar y utilizar: Sending Email With PHPMailer, Integrate CakePHP with Kcaptcha, Google Geocoder, LastRSS CakePHP Component, Pagination Component, etc. Y otros que ya vienen incluidos con el núcleo cake: AuthComponent (Gestión y autenticación de usuarios), RequestHandler (Obtener información de las peticiones http), CookieComponent (Gestor de cookies), AclComponent (Access Control List), EmailComponent (Envio de mails), SecurityComponent (Incrementar la seguridad de tu aplicación), SessionComponent (Gestor de session). Y podemos crear nuestros propios componentes para cumplir diferentes requisitos:

Crear un nuevo componente para cakephp es muy sencillo. Basta con crear un fichero en app/controllers/components/fichero.php con una clase nombrada FicheroComponent que tendrá una variable $controller y un método:
[php]
function startup( &$controller ) {
$this->controller = &$controller;
}
[/php]
Luego para hacer uso de un componente en uno de nuestros controladores simplemente lo añadimos al array
[php]
var $components = array(‘NuestroComponente’,'OtroComponente’);
[/php]
y ya lo tendremos disponible como
[php]
$this->NuestroComponente
[/php]

Aqui tenemos un buen ejemplo de uso del json component.

Helpers:
Respecto a los helpers también los tenemos incluidos en el núcleo cake: html (ayuda a contruir tags html), form (ayuda a contruir formularios), number (ayuda a formatear numeros), timer (ayuda a formatear fechas), xml (simplifica la construcción de documentos xml), ajax (uso de ajax mediante prototype). Su uso es tan sencillo como:
[html]


[/html]

Al igual que los componentes también podemos desarrollar nuestros propios helpers, aqui tenemos un buen ejemplo donde se crea un helper para autocompletar un input text mediante ajax .

1 Comment

Controlando mi tiempo con Hamster

Captura hamster
Desde que trabajo con una relativa flexibilidad de horarios necesito mas que nunca llevar un estricto control sobre el tiempo que dedico a ciertas tareas.

En otros posts pasados había hablado de rememberthemilk como un fantástico gestor de tareas online, que había mejorado considerablemente en las últimas versiones y sobre todo con su última integración con gmail. Lo mantengo y sigo utilizando. Pero ahora necesito además asignar tiempos a estas tareas, o mejor, a un conjunto de estas.

Después de unas semanas de prueba con varias utilidades: gtimer, gnotime, wmwork, worklog, gtimelog creo que finalmente he encontrado lo que buscaba: hamster. Visualmente correcto, funcionalmente sencillo pero suficiente, justo lo que necesito, alta/baja de tareas agrupadas por categorías y asignación de tiempos a cada tarea. Suficientes resúmenes estadísticos e integración con la barra de menús de gnome.

Pero como sabéis hace un tiempo que me pasé a xfce, así que he tenido que instalar el xfce4-xfapplet-plugin mediante el que podemos incluir en nuestra barra de menú de xfce cualquier applet gnome.

Leave a comment

Netbeans IDE for PHP

Hoy, después de pelearme con el eclipse un rato (tampoco fue como para una separación seria, solo unos días hasta que se me pase) me he dado una vuelta por netbeans y me entero de que la nueva versión 6.1 ya trae el plugin integrado para soportar php. Es mas, nos podemos descargar una versión de este ide solo con el plugin para php por la módica cantidad de 16MB.

La he instalado y las primeras impresiones son buenas pero…

El editor está bien, el autocompletado de funciones funciona!, la refactorización se reduce a renombrado de ficheros y ni siquiera lo hace bien, excelente integración con svn (igual que la versión javera), en principio parece que la integración con xdebug es bastante buena pero solo lo he usado con proyectos demo.

Pero… el mismo pero de siempre, sigue siendo muy pesado, consume una grandísima cantidad de memoria. Será momento de plantearme un cambio de equipo? mmm, no se no se, creo que aguantaremos un poquillo mas.

http://wiki.netbeans.org/PHP

Leave a comment

Propel, un orm para PHP

Logo PropelAyer un compañero de trabajo me habló de propel el cual no conocía (gracias Juanjo :-) ). Es un orm para php basado en torque competencia directa del conocido hibernate en el mundo j2ee.

Propel está disponible en los repositorios de pear por lo que su instalación puede llegar a ser de lo mas sencillo si utilizamos estos repositorios:
[code]
sudo pear channel-discover pear.phpdb.org
sudo pear install phpdb/propel_generator
sudo pear install phpdb/propel_runtime
[/code]
o igualmente sencilla al estilo tradicional, descargamos paquetes, descomprimimos paquetes :-) .

Propel depende de otros paquetes pear que necesitamos tener instalados (phing, creole y opcionalmente Log):
[code]
sudo pear channel-discover pear.phing.info
sudo pear install phing/phing

sudo pear channel-discover pear.phpdb.org
sudo pear install phpdb/creole
sudo pear install phpdb/jargon
[/code]

También necesitaremos el modulo php5-xls si no lo tenemos ya, un simple apt-get install php5-xls bastará en ubuntu.

En el directorio propel/generator/projects tenemos un proyecto “bookstore” que utilizaremos para nuestra primera toma de contacto. Tenemos 3 ficheros:
- build.properties: Definimos las propiedades de nuestro proyecto necesarias para generar nuestros modelos a partir de las definiones xml.
- runtime-conf.xml: Definimos las propiedades de nuestro proyecto, nombre, conexión con BD, paquetes de clases a generar, etc, a utilizar en nuestro proyecto, este xml se trasformará una vez construido el modelo de clases en un array de datos definido en nuestro próximo fichero de configuración.
- shema.xml: La definición de nuestro modelo de datos a partir del que generar el modelo de clases y los scripts .sql necesarios para generar nuestra BD.

Una vez tenemos los ficheros anteriores correctamente configurados simplemente necesitaremos ejecutar:
[code]
./propel-gen ../projects/bookstore
[/code]
Script que encontramos en propel/generator/bin y que nos genera dentro de nuestro proyecto un directorio build con:
- clases: Todas las clases que representan a nuestro modelo de datos y a través de las cuales nos comunicaremos con nuestra BD.
- conf: Nuestros ficheros de configuración, aquel generado a partir del anterior runtime-conf.xml.
- sql: Los scripts *.sql para contruir nuestra BD.

El que para generar una entidad necesite crear 5 ficheros me resulta engorroso, creo que muchas de las funcionalidades escritas en estas clases deberían estar incluidas en el núcleo propel:
- Entidad.php: Clase vacía que deberemos utilizar para extender la funcionalidad de esta entidad.
- EntidadPeer.php: Clase vacía que deberemos utilizar para extender las operaciones de consulta y actualización contra la tabla a la que representa esta entidad.
- om/BaseEntidad.php: Clase generada con todos los atributos getters&setters y demás operaciones de nuestro modelo definido en el xml.
- om/BaseEntidadPeer.php: Operaciones básicas de consulta y actualización contra la BD a la que representa esta entidad.
- map/EntidadMapBuilder.php

No creo que lo utilice por ahora, me gustaría que tuviera un nivel abstracción mayor sin tener que recurrir a la generación de código, y por otro lado el proyecto al que podría aplicarlo ahora mismo estimamos que deberá soportar una gran cantidad de tráfico y creo que nuestros DAOS serán mas eficientes, de todas formas lo seguiré de cerca.

Os dejo una presentación de Hans Lellelid (uno de los directores del proyecto):

2 Comments

Php5 y php4 también conviven en mi ubuntu

En días como hoy es cuando se echa de menos un hombro donde desahogar las penas, un compañero al que preguntar, o simplemente al que decir “¿esta bien verdad?, ¿y pq no funciona entonces?, es que no lo entiendo, ¿enviamos un bug?…y mil cosas mas sin sentido cuando finalmente encuentras los porqués”.

Volviendo al proyecto en el que ya estoy sumergido necesito además de una 4 de mysql una 4 de php, y claro en mi ubuntu estoy con la 5. Venga a buscar soluciones.

Para tener 2 versiones de php corriendo en la misma máquina, sin virtualizaciones ni nada que este cacharro no esta para esos trotes, necesitamos tener una instalada como módulo y otra como cgi. Como módulo tengo la 5.2.3 y necesito instalar una 4 como cgi.

Voy a recurrir a los repositorios de http://www.dotdeb.org/mirrors para hacerme con la 4.4.8. Edito mi sources.list y añado los repositorios de dotdeb.

Tras actualizar los repositorios hago un apt-get install php4-cgi y primera en la frente, dependencia libzzip-0.12 incumplida (paso mucho miedo, pero con suerte no es recursiva), es lo que tiene recurrir a estas versiones antiguas empaquetadas. Nos vamos a debian http://packages.debian.org/etch/i386/libzzip-0-12/download descargamos e instalamos el paquete.

Ahora si apt-get install php4-cgi y php4 instalado. Instalamos además otros paquetes que necesitaremos apt-get install php4-curl php4-domxml php4-gd php4-gmp php4-imap php4-ldap php4-mcal php4-mcrypt php4-mysql

Ahora que tenemos php4 instalado y nuestro ejecutable en /usr/lib/cgi-bin/php4, editamos nuestro virtual host de apache:
[xml]

ServerAdmin sanroman.javier@gmail.com
ServerName midominio.com
DocumentRoot /home/javi/php4/miproyecto

ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

AddHandler php-script .php
Action php-script /cgi-bin/php4
Options FollowSymLinks
AllowOverride None


[/xml]
y tenemos que activar el modulo actions (a2enmod actions) o no podremos ejecutar la linea Action php-script /cgi-bin/php4 .
Y con esto ya tenemos este virtual host utilizando la 4. Ala mañana mas que hoy ya es tarde.

4 Comments

Extendiendo el controlador de cakephp

Este fin de semana el cake me hizo otra de las suyas. Aunque pensándolo bien siempre podemos disculparlo por trabajar en beta.

El caso es que yo necesitaba mi propio AppController para incluir una serie de acciones comunes a todas las peticiones, y que se ejecutarían en el beforeRender() (justo antes de renderizar la vista y después de ejecutar toda la lógica de los controladores).

Esto en cake 1.1 se hacía copiando el app_controller.php a la raíz de /app, sobreescribíamos los métodos necesarios y listo. Y claro antes de leer nada fue lo primero que hice en cake 1.2. Pero no tuve suerte. Resulta que no encontraba los métodos que estaba declarando. Cake no estaba cargando mi app_controller sino el por defecto en /cake/libs/controller.

De primeras acudí a google (no conozco otra forma mas rápida de encontrar solución a este tipo de problemas) y tras comprobar que era al único que le sucedía tal cosa me fuí directo a http://manual.cakephp.org/complete/3/the-manual y la sorpresa cuando me encuentro con estas líneas:

Both controllers, helpers and models have a parent class you can use to define application-wide changes. AppController (located at /app/app_controller.php), AppHelper (located at /app/app_helper.php) and AppModel (located at /app/app_model.php) are great places to put methods you want to share between all controllers, helpers or models.

Lo estaba haciendo bien!, tras navegar por el registro de bugs llegué a esta conversación en el grupo de google , que seria de mi sin la comunidad!, resulta que para extender el app_controller en cakephp 1.2 debes situarlo en /app/controllers/app_controller.php y no en /app/app_controllers.php.

No me quejo, es el riesgo que se corre por trabajar en betas, además, quitando estos dos detalles cake y yo nos llevamos bastante bien. Aunque eso si, prefiero no tener documentación a tener documentación mentirosa.

5 Comments

Mysql5 y mysql4 conviviendo en ubuntu

Logo MysqlPues si con este inicio de mayo y un año mas encima :-) cambiamos de proyecto y necesariamente hemos de utilizar mysql4.

En mi ubuntu gutsy (todavía no me he atrevido a actualizar) tengo instalada mediante apt la versión 5, así que no me quedaba otra que buscar la forma de tener las 2 funcionando en mi portatil ya que la opción de servidor de desarrollo en casa a día de hoy es inviable. Yo he compilado los fuentes de mysql4 para conseguirlo aunque tenemos otras opciones. En este provechoso articulo tenemos información sobre esto.

Lo primero es descargar los fuentes.
Descomprimimos y preparamos la compilación para indicar el puerto, socket y directorio de instalación, todos diferentes a la versión 5 actual claro:
[code]
./configure --prefix=/home/javi/mysql4.1 --sysconfdir=/home/javi/mysql4.1 --with-tcp-port=3309 --with-mysqld-user=javi --with-unix-socket-path=/home/javi/mysql4.1/mysql4.1.sock
[/code]

Compilamos “make” e instalamos “make install”.

Copiamos el fichero de configuración a la nueva instalación:

[code]
cp support-files/my-large.cnf /home/javi/servers/mysql4/my.cnf
[/code]

Creamos las BD (test, mysql, information_schema) necesarias para mysql ejecutando ./bin/mysql_install_db.

Iniciamos ./bin/mysqld_safe –defaults-extra-file=my.cnf indicando el fichero de configuración a utilizar.

Y listo, probamos si ha iniciado correctamente realizando una conexión: ./bin/mysql -h 127.0.0.1 -P 3308 -u root, especial atención a la ip y no “localhost” para que la conexión se realice mediante TCP/IP.

Y a currar en 5 y 4.

3 Comments

Curso J2EE (5ª semana) – JAX-WS

Java Xml
Nunca es tarde si el post llega…. bueno era algo así ¿no?. El caso es que después de bastante tiempo he aprovechado este puentecillo en el que tampoco tendremos curso para quitar este post atrasado.

En esta 5ª semana llegó el fin de los ejb’s con un último ejemplo de ejb de mensaje (jms) que no voy a reproducir pues es muy parecido al ejemplo del post anterior. Y a continuación comenzamos con los servicios web, esa tecnología tan inmadura (por lo que cuidadín con las elecciones, cambios continuos y en general un jaleo de nombres, apis, versiones…) como de moda últimamente. Eso si!!, sin antes perder 3 horillas en una creo que inútil charla de igualdad de género a la que la xunta nos obliga en todos los cursos que financia, en fin, creo que los burros a esta edad seguirán siendo burros, y tampoco me parece el marco ideal para dar estas lecciones, opinión muy personal por supuesto.

Los servicios web son un conjunto de tecnologías (independientes de lenguaje y plataforma) que nos permiten el intercambio de datos entre diferentes máquinas conectadas a través de una red. Lo típico es utilizarlos bajo http (pues junto con su estándar son las dos grandes ventajas aportadas) y eliminar así los efectos de los firewalls (seguro que alguna vez habéis topado con uno). De todas formas os dejo un par de enlaces donde explican mucho mejor que yo:

http://www.w3c.es/Divulgacion/GuiasBreves/ServiciosWeb
http://es.wikipedia.org/wiki/Servicio_Web

Un breve esquema (desde el w3c):
Servicios web
Vemos la aplicación cliente que se conecta con el servicio web, envía datos a través de mensajes SOAP según las reglas descritas en el “contrato” WDSL.

En java tenemos api’s y herramientas que nos ayudan a crear y desplegar servicios web. JAX-WS (que forma parte del proyecto glassfish y agrupa entre otras a SOAP 1.2, WSDL 1.1, WSDL 2.0, JAXB 2.0) nos abstrae de las tareas básicas para crear un servicio web. Nos aporta 2 buenas utilidades wsgen y wsimport que nos permitirán generar de forma automática los artefactos necesarios para generar nuestro servicio y las clases proxy que representarán el servicio web en local para los clientes. Luego a través de anotaciones, como viene siendo habitual, indicaremos que clase representa nuestro servicio, que propiedades se corresponden con los tags de nuestros xml, etc:
[java]
@WebService(name=”ServicioAlumnos”)
public class AlumnoWsFacade {

public @WebResult(name=”alumno”)AlumnoBean getAlumno()
{
[/java]
[java]
public class AlumnoBean {
private String nombre;
@XmlElement(name=”nombre”)
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
[/java]

Un par de sencillos pero útiles ejemplos:
http://java.sun.com/developer/technicalArticles/J2SE/jax_ws_2/
http://java.sun.com/developer/technicalArticles/J2SE/jax_ws_2_pt2/

Y para terminar necesitamos un servidor que soporte jax-ws, en realidad nos serviría el propio tomcat, pero yo sigo trabajando con jboss así que me tocó instalar el soporte jax-ws que nos provee el paquete jbossws:
1- Descargamos jbossws.
2- Descomprimimos y renombramos ant.properties.example por ant.properties.
2- Editamos ant.properties y modificamos la propiedad jboss422.home indicando el directorio de nuestro jboss.
3- Ejecutamos ant deploy-jboss42 (mi versión es la 4.2 sino la que toque).
4- Iniciamos jboss y comprobamos en la dirección http://localhost:8080/jbossws/ que se ha instalado el soporte jax-ws en nuestro jboss.

Con esto ya tendríamos jboss preparado para desplegar servicios web, ahora solo nos falta hacer unas pruebecillas, quizás en otro post…

Leave a comment

Sistemas de plantillas para PHP o PHP como sistema de plantillas

Cuantas veces este ha sido motivo de debate. ¿Merece la pena utilizar un sistema de plantillas estilo smarty para php?. ¿Acaso no es php un lenguaje de script suficientemente limpio y potente como para poder valerse por si solo como motor de plantillas?. ¿Que diferencia encontráis entre estas 2 lineas?:
[html]

{nombre}

[/html]
¿De verdad creéis que la primera es mas sencilla?.

Como ya habréis intuido yo nunca estuve de acuerdo en utilizar un lenguaje añadido de plantillas, básicamente porque no me aporta nada. Por supuesto que estoy de acuerdo en separar las capas de presentación y lógica pero esto lo podemos hacer tanto con php como no hacerlo con cualquier motor de plantillas. Todo depende de como lo utilicemos.

Pero yo prefiero esto:
[php]
//posts.php
$posts = getPosts();
include(“posts.html”);
[/php]
[html]
//posts.html

getTitle()?>

[/html]

y no esto:

[php]
//posts.php
require(“smarty/Smarty.class.php”);
$template = new Smarty;

$template->template_dir=”.”;
$template->assign(“posts”,getPosts);
$template->display(posts.html);
[/php]
[html]
//posts.html

{foreach from=$posts item=post}

{person.getTitle}

{/foreach}

[/html]

Por cierto tanto cakephp como zend framework han adoptado la primera opción de forma nativa, lo que no quiere decir que no existan plugins para poder utilizar algún lenguaje propio de plantillas.

2 Comments

Ejemplo EJB stateless

Lo prometido es deuda y ahora q se me ha pasado la vagancia y además tenía un ratillo libre (combinación compleja donde las halla) ;-) os dejo un ejemplo de un ejb sin estado (stateless).

Yo he utilizado jboss en su última versión estable (4.2.2.GA) como contenedor del ejb, para utilizarlo solo teneis que descargaros una copia y arrancar ejecutando /bin/run.sh, ¿fácil verdad?. Podriamos haber utilizado glassfish, que en ubuntu se queda la instalación en un maravilloso apt-get install glassfish, pero si os parece eso lo dejamos para otro día.

Vamos con nuestro ejb.

Primero nos creamos el bean que encapsula toda nuestra lógica de negocio. En este caso tendremos solo 2 métodos, para sumar y restar 2 números (operaciones básicas de toda calculadora).

[java]
package net.jsanroman.ejb3stateless.ejb.stateless;
import javax.ejb.Stateless;
import net.jsanroman.ejb3stateless.ejb.interfaces.CalculadoraLocal;
import net.jsanroman.ejb3stateless.ejb.interfaces.CalculadoraRemote;

@Stateless
public class CalculadoraBean implements CalculadoraRemote, CalculadoraLocal
{
public static final String RemoteJNDIName = CalculadoraBean.class.getSimpleName()+”/remote”;
public static final String LocalJNDIName = CalculadoraBean.class.getSimpleName()+”/local”;

public int add( int x, int y ){return x+y;}
public int subtract (int x,int y){return x-y;}
}
[/java]
Destacar el uso de la anotación @Stateless para indicar el tipo de ejb que estamos creando.

A continuación creamos las interfaces CalculadoraLocal y CalculadoraRemote para indicar que métodos serán accesibles desde el propio contenedor o desde fuera y que serán implementadas por nuestro bean anterior.

En nuestro caso solo nos interesa acceder desde remoto pues haremos las pruebas desde un script fuera de nuestro contenedor.

[java]
package net.jsanroman.ejb3stateless.ejb.interfaces;
import javax.ejb.Local;
@Local
public interface CalculadoraLocal {
}
[/java]

[java]
package net.jsanroman.ejb3stateless.ejb.interfaces;
import javax.ejb.Remote;
@Remote
public interface CalculadoraRemote {
public int add(int x, int y);
public int subtract( int x, int y);
}
[/java]

Ya tenemos nuestro ejb creado, lo empaquetamos en un .jar (tareilla ant) y lo soltamos en jboss/server/default/deploy. Si nos fijamos en el log de jboss podremos averiguar si se ha producido algún error, pero para estar completamente seguros nos vamos a la jmx-console http://localhost:8080/jmx-console/ y comprobamos si se ha cargado nuestro ejb, en mi caso aparecen estas lineas que indican que está listo para ser utilizado:

# jar=ejb3_stateless_calculadora.jar,name=CalculadoraBean,service=EJB3
# module=ejb3_stateless_calculadora.jar,service=EJB3

Llegados a este punto tan solo nos queda desarrollar un sencillo cliente que haga uso del ejb recién creado. Con una simple clase que muestre el resultado por consola es suficiente para esta prueba:

[java]
package net.jsanroman.ejb3stateless.client;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import net.jsanroman.ejb3stateless.ejb.interfaces.CalculadoraRemote;
import net.jsanroman.ejb3stateless.ejb.stateless.CalculadoraBean;
public class CalculadoraClient {
public static void main(String [] args){
Properties properties = new Properties();
properties.put(“java.naming.factory.initial”,”org.jnp.interfaces.NamingContextFactory”);
properties.put(“java.naming.factory.url.pkgs”,”=org.jboss.naming:org.jnp.interfaces”);
properties.put(“java.naming.provider.url”,”localhost:1099″);
Context contexto = null;
try{
contexto = new InitialContext(properties);
CalculadoraRemote beanRemoto = (CalculadoraRemote)
contexto.lookup(CalculadoraBean.RemoteJNDIName);
int resultado = beanRemoto.add(1, 9);
System.out.println(“El resultado es:”+resultado);
}
catch( NamingException e )
{
e.printStackTrace();
}
}
}
[/java]

Simplemente destacar la linea contexto.lookup(CalculadoraBean.RemoteJNDIName); causa de posibles rompederos de cabeza y que nos da acceso a nuestro ejb.

Ala y ahora a hacer pruebas con los diferentes ejb’s, el ejb-ql, a probar desde otra máquina, y lo que se nos ocurra.

1 Comment