Ajax en CakePHP

Ajax (Asynchronous JavaScript? and XML) es un conjunto de tecnologías que nos permite evitar la sobrenavegación y tener un experiencia en el Web más similar a la que tenemos con las aplicaciones de escritorio como OpenOffice?.org o Nautilus.
Ajax se construye en torno al XMLHttpRequest, un objeto JavaScript? (JS) que nos permite hacer peticiones al Webserver "tras bambalinas" o en "background" sin tener que volver a recargar la página en el navegador.
Podemos usar el objeto XMLHttpRequest directamente en una función JS escrita por nosotros, pero es necesario considerar el navegador y la versión para construir el objeto, por ejemplo para construir el objeto para las diferentes versiones de Explorer:
// Provide the XMLHttpRequest class for IE 5.x-6.x:
if( typeof XMLHttpRequest == "undefined" ) XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
throw new Error( "This browser does not support XMLHttpRequest." )
};
Esto es tedioso, afortunadamente han surgido varios frameworks JS que facilitan mucho trabajar con Ajax y se encargan (entre otras cosas) de lidiar con la versión y tipo de navegador. Los más usados de estos frameworks son Prototype y jQuery, ambos son usados en los proyectos de Chipotle Software, tanto en CakePHP como en Django. Además existe un animation framework Scriptaculous que funciona junto con Prototype para agregar efectos visuales a nuestras peticiones ajax.
Ajax Helper
En el caso de CakePHP se usa Prototype y Script.aculo.us, ambos se deben descargar y colocar en el directorio APP/webroot/js/ de nuestra aplicación. Una vez hecho esto se cargan en la zona HEAD del layout del sitio de este modo:
if ( isset($javascript) ): // comprueba que el Javascript helper está activado
echo $html->charset('UTF-8');
echo $javascript->link('prototype');
echo $javascript->link('scriptaculous.js?load=effects');
endif;
El Javascript helper y Ajax helper deben estar declarados en el controlador. Para usar Ajax en CakePHP se siguen los siguiente pasos:
1) Se usa el Ajax helper para construir un objeto que llame al método de un controlador, el objeto puede ser un link o un botón de formulario. 2) Se define un div con id único ("qn" por ejemplo). 3) Se coloca una imagen animada pero con el atributo "visibility:none" para que permanezca oculta. 4) Al dar click sobre el objeto se llama al controlador en "background" y la imagen se hace visible para decirle al usuario que su petición está trabajando. 5) Al terminar el request el resultado se carga en "qn" y la imagen se vuelve a ocultar.
Por ejemplo en una vista tenemos el siguiente código:
$ajax->link( // este es un ajax link
$html->image('static/show_icon.png',array('alt'=>__('Course description',true), 'title'=>__('Course description',true))),
'/vclassrooms/description/'.$data['Vclassroom']['ecourse_id'], // la llamada al método description
array('update' => 'qn', // el div donde se cargará el resultado
'loading'=>"Element.show('loading');", // muestra la imagen
'complete'=>"Element.hide('loading');Effect.Appear('qn')"), // al completarse la imagen se vuelve a ocultar y se muestra el div qn
null,false)
);
echo $gags->imgLoad('loading'); // para detalles ver el gags helper
echo $ajax->div('qn', array('style'=>'padding:3px')).$ajax->divEnd('qn'); // esto es sólo es un div vacío
El método description del controlador vclassrooms es asi:
public function description($ecourse_id)
{
$this->set('description', $this->Vclassroom->Ecourse->field('description', array('Ecourse.id'=>$ecourse_id)));
$this->render('description', 'ajax'); // ejecuta y devuelve la vista description.ctp en modo ajax es decir sin el layout
}
Esto quiere decir que existe la vista APP/views/vclassrooms/description.ctp y que luego de procesarse el resultado se coloca en el div "qn" de la vista donde ejecutamos la petición Ajax. La vista description.ctp es como cualquier otra vista de Cake:
//esto se coloca en el div qn luego de dar clic al elemento Ajax
echo $hmtl->div('title', $data['Ecourse']['title']);
echo $hmtl->div('desc', $data['Ecourse']['description']);
Otro ejemplo
Podemos usar Ajax en un formulario, usando la opción submit para construir un botón que envia los datos al método del controlador:
echo $ajax->form();
echo $form->input('Model.field');
echo $ajax->submit('Vote', array('url' => '/pollrows/vote',
'update' => 'add_pollrow',
'loading' => "Element.hide('add_pollrow');Element.show('loading')",
'complete' => "Element.hide('loading');Effect.Appear('add_pollrow')"
));
Si en lugar de una liga usamos Ajax en un formulario podemos recibir y usar los datos en el método del controlador igual que siempre es decir:
$this->data['Model'] = Sanitize::clean($this->data['Model']); $this->Model->save($this->data);
Permisos
Esté método description() (y cualquier otro método que usemos en Ajax) debe tener permisos de ejecución en el Auth Component o no se ejecutará,es decir denos agregar el método al array de los métodos permitidos :
public function beforeFilter()
{
parent::beforeFilter();
$this->Auth->allow(array('display', 'aboutme' 'description', 'chat'));
}
Para desarrollar y depurar código Ajax es casi indispensable usar la extensión Firebug para Firefox pues asi podemos ver las respuesta de error y lo que envia Apache y CakePHP en "background".
Encoding
Al trabajar con Ajax se debe coordinar desde el incio que el Webserserver (Apache2), la BD (PostgreSQL), el lenguaje (PHP5) y el framework (CakePHP) tengan el Default Charset en UTF-8 y asi no tendremos problemas con las eñes y acentos.
En el caso de PostgreSQL si no se hizo desde el inicio es necesario hacer un pg_dump de la BD actual y crear una nueva base de datos con el encoding correcto:
$createdb -E UNICODE DBNUEVA
Y cargar en ella los datos para que los guarde correctamente.
Live Chat en Karamelo
Karamelo tiene una implementación de Livechat que usa Ajax:
1) El modelo Chat guarda los mensajes del chat del vclassroom (Chat->belongsTo->Vclassroom).
2) El usuario pincha en el icono de chat del vClassroom que llama al método chat() del controlador vclassrooms que carga los mensajes.
3) La función Ajax getChatText(vclassroom_id) de la vista chat.ctp busca mensajes nuevos cada tres segundos y los coloca en el div updater.
4) Por otro lado la función Ajax sendPing(vclassroom_id) de la vista chat.ctp avisa al sistema que el usuario está y se mantien en el chat.
5) El elemento chat_messages.ctp es el que hace el loop con formato para el div updater.
Attachments
-
unnamed.png
(60.5 KB) -
added by anonymous 8 months ago.
-
unnamed.pdf
(27.0 KB) -
added by anonymous 8 months ago.
