9 September, 2009

Swiftmailer, gmail y cakephp

Bastante tiempo sin escribir ya. Desde la última vez: unas cortas y merecidas vacaciones, comienzo de un proyecto muy ilusionante del que espero hablar algún dia (lo contrario sería una mala noticia), mucho trabajo, y por último una gran noticia pero que me trae en vilo últimamente. En fin que todo a su debido tiempo e intentando mantener la cabeza bien fría.

En mi macbook no tengo ningun servidor de smtp instalado, ni quiero si no es absolutamente necesario. Por ello que para hacer diferentes pruebas de envio de mail desde local utilizo servidores externos. Tengo una cuenta creada en google para este fin, en este caso concreto utilizo cakephp, y ni el componente que este trae por defecto ni phpmailer pueden conectarse con las cuentas gmail al no soportar TLS (Trasport Layer Security), protocolo de autentificación utilizado por gmail.

Buscando otras opciones me encontré con SwiftMailer, y aunque sería sencillo desarrollar un componente que haga uso de esta librería ya lo han hecho por nosotros http://bakery.cakephp.org/articles/view/swiftmailer-component.

Este componente que nos descargamos para cakephp usa sendmail por defecto, pero si lo que necesitamos (por ejemplo una vez subamos a producción) es simplemente usar la función mail() de php, SwiftMailer nos ofrece un wrapper sobre la misma mediante la clase Swift_MailTransport.

28 May, 2008

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:

  1. function startup( &$controller ) {
  2.      $this->controller = &$controller;
  3. }

Luego para hacer uso de un componente en uno de nuestros controladores simplemente lo añadimos al array

  1. var $components = array('NuestroComponente','OtroComponente');

y ya lo tendremos disponible como

  1. $this->NuestroComponente

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:

  1. <div id="header">
  2.    <h1><?php echo $html->link(__('Portada', true), $html->base.'/portada'); ?></h1>
  3. </div>
  4. <!--Hacemos uso del helper $html tanto para crear un link como para obtener la dirección base de nuestra web.-->

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 .

6 May, 2008

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 March, 2008

Cuidadín con las stables, cake

Logo CakePHPEsta noche he soñado con el bug que soluciona este changeset (https://trac.cakephp.org/changeset/3983).

Resulta que hasta ayer había estado probando la beta de cakephp y todo era una maravilla. Ayer mismo me bajé la stable para comenzar a trabajar en el proyecto final y dejarme de pruebas, la primera en la frente. Nada mas crear mi controlador y mi modelo para el scaffolding aparece el primer error, algo como:

Notice: Trying to get property of non-object in /home/javi/proyectos/php/cakephp/cake/libs/controller/controller.php on line 666

Me aseguré de que había bajado la estable, de las compatibilidades con mi sistema, no encontré mucha información por internet, así que nada me puse a bucear, le seguí el rastro, desde el controller.php pasé al model_php5.php luego al inflector.php al object.php ¿y donde terminé? pues en el class_registry.php.

Resulta que class_registry.php es la clase contenedora de los objectos que representan nuestro modelo. Estos se almacenan en esta clase en un array, ya sabeis clave=>valor. Hasta aquí todo bien. Pero en el controller.php en la linea 666 parece que el objecto que se estaba intentando cargar no existía, estaba vacío. Bien bien ya casi estaba. Solo nos quedaba comprobar como almacenábamos el objecto y como lo recuperábamos. Pero ya era tarde, mi cabeza ya no pensaba, así que decidí dejarlo para hoy, ERROR, mis sueños con el cake casi no me dejan dormir.

Esta mañana con la cabeza fresca lo he encontrado. Resulta que el objecto se estaba almacenando con una clave y se estaba recogiendo con otra diferente. Esto solo pasaba cuando tu modelo tenia varias palabras (ej: BiciCarreras). ¿Demasiado obvio verdad?, si seguro que no era esto, algo estaría haciendo yo mal. Pues NO.

El cake cuando recupera un objecto pasa la clave del mismo por este filtro $key = Inflector::underscore($key); que convierte la clave a minúsculas e incluye un "_" entre palabra y palabra, en nuestro caso nos quedaría (bici_carreras). Pues bien cuando lo almacenaba no pasaba la clave por este filtro y lo único que hacía era convertir la cadena a minúsculas $key = strtolower($key);, con lo que nos almacenaba el objecto con la clave (bicicarreras).

El bug está corregido para la beta 1.2 lo podéis comprobar en este changeset https://trac.cakephp.org/changeset/3983 pero no para la stable 1.1. ¿Curioso? no, tocapelotas.

4 March, 2008

CakePHP + Scaffolding

Logo CakePHPHace aproximadamente un mes que me había animado a conocer un poco mas a fondo cakephp, un framework MVC en y para php. Pero como tantas otras veces me había quedado a medias presionado por la carga de trabajo por aquel entonces. Ahora ha surgido de nuevo la oportunidad y parece que será la definitiva.

Una de las características mas cool (y lo dicen ellos en su manual "Cake's Scaffolding is Pretty Cool"), es lo que ellos llaman Scaffolding, un sistema mediante el cual tu simplemente defines un controlador que trabaja sobre un modelo y cake te crea toda la interfaz de gestión (crear, editar, eliminar elementos) de esa tabla.

Si utilizas una nomenclatura de tablas y campos clave estándar para cake, no necesitaras ni tan siquiera definir un modelo, simplemente será suficiente con crear por ejemplo este código:

  1. <?php
  2. class BiciController extends AppController
  3. {
  4.   var $scaffold;
  5.   //var $uses = array('Auto'); // Si quisieras utilizar un modelo y este tuviera un nombre diferente de Bici
  6. }
  7. ?>

en un fichero bicis_controller.php en la raiz de app/controllers.

Si utilizas tu propia nomenclatura o heredas un diseño de BD ya creado, tienes diferentes variables para configurarlo, en este caso necesitarás crear el BicisController anterior y además el modelo Bici:

  1. <?php
  2. class Bici extends AppModel
  3. {
  4.   var $name         = "Bici";
  5.   var $useTable  = "bicis"; // Aquí podríamos indicar que tabla está utilizando este modelo
  6.   var $primaryKey        = "idbici"; // Si la clave principal de nuestra tabla car es diferente de id
  7. ?>

y lo almacenamos como bici.php en app/models.

Seguro que estáis pensando que para este caso tan sencillo claro que está muy bien, pero, ¿y cuando tenemos un modelo de datos mas complejo con diferentes tipos de relaciones?. Pues también tenemos opciones. Cake soporta 4 tipos de relaciones entre tablas: hasOne, hasMany, belongsTo y hasAndBelongsToMany. Como ejemplo imaginemos que la Bici definida en el modelo anterior es de un solo color. Esta relación la definimos así en la clase modelo Bici:

  1. <?php
  2. class Bici extends AppModel
  3. {
  4.   var $name         = "Bici";
  5.  
  6.   var $belongsTo = array('Color' =&gt;
  7.     array('className'    =&gt; 'Color',
  8.     'conditions'   => '',
  9.     'order'        => '',
  10.     'foreignKey'   => 'color_id'
  11.   )
  12. );
  13. ?>

y debemos definir el modelo del Color:

  1. <?php
  2. class Color extends AppModel
  3. {
  4.   var $name         = "norma";
  5.   var $displayField = "titulo"; // El campo que se mostrará en el select que nos permitirá relacionar el car con el color
  6. }
  7. ?>

Para terminar decir que cakephp es mucho mas que scaffolding. Esta es una forma de crear una interfaz sencilla y de una forma muy rápida, pero cake nos permite crear nuestras propias interfaces, nuestra propia lógica de negocio, validaciones, etc.
Para mas información ya sabéis www.cakephp.org

Powered by WordPress
Bajo licencia Creative Commons
Contacto sanroman.javier at gmail.com