Habiendo dejado mucho tiempo de escribir artículos sobre Symfony me gustaría hablarles hoy sobre la utilización de Ajax con jQuery dentro de nuestro Framework PHP. Antes de leer este artículo recomiendo la lectura de los artículos de la serie de jQuery y Ajax en donde se explica como generar de una manera muy sencilla peticiones asíncronas al servidor utilizando la librería JavaScript jQuery. En estos artículos verán el concepto erróneo que muchas veces tenemos sobre Ajax y entenderán la idea sobre Hijax.
Symfony en sus versiones anteriores contaba con helpers interesantes para la creación de links y formularios utilizando Ajax mediante prototype. Así como existe hoy en día el helper para link_to()
existía un link_to_remote()
que era capaz de crear el código JavaScript necesario para la llamada Ajax. Con el tiempo, en las versiones más maduras del framework esto fue eliminado y se creó un plugin que utiliza jQuery llamado sfJqueryReloadedPlugin que continúa con las funciones más utilizadas. El enlace al plugin lo pueden encontrar aquí donde podrán ver la documentación necesaria.
La idea de este artículo NO es sobre la utilización del plugin sino sobre cómo ejecutar las llamadas Ajax directamente desde cero para entender la idea y poder hacer lo que necesitemos sin depender del plugin.
Como veíamos en los artículos de la serie sobre jQuery y Ajax, repetimos varias veces que la llamada asíncrona es simplemente un request al servidor y que cualquier cosa que escribamos en la salida estándar de la página procesadora es devuelto como response al cliente. La misma idea la manejaremos aquí ya que nada en absoluto cambia.
Para hacer las pruebas, dentro de un proyecto de Symfony (versión actual 1.4.9), crearemos un action «test» y otro «procesador» en los cuales trabajaremos.
En primer lugar en el archivo view.yml agreguemos el jQuery, de la siguiente manera. Esto va a requerir que copiemos el archivo jquery-1.5.min.js a la carpeta /web/js/
[text highlight=»14″ title=»Archivo: apps/frontend/config/view.yml»]
default:
http_metas:
content-type: text/html
metas:
#title: symfony project
#description: symfony project
#keywords: symfony, project
#language: en
#robots: index, follow
stylesheets: [main.css]
javascripts: [jquery-1.5.min.js]
has_layout: true
layout: layout
[/text]
Una vez que tenemos importada la librería del jQuery, creemos nuestros actions, cada uno con un template.
[php title=»Archivo: apps/frontend/modules/pruebas/actions/actions.class.php»]
public function executeTest(sfWebRequest $request)
{
}
public function executeProcesador(sfWebRequest $request)
{
}
[/php]
[php htmlscript=»true» title=»Archivo: apps/frontend/modules/pruebas/templates/testSuccess.php»]
<a id="test" href="<?php echo url_for(‘principal/procesador’) ?>">Cargar información</a>
<div id="container" style="border:1px solid #000;width:300px;height:300px;overflow:auto;"></div>
[/php]
[html title=»Archivo: apps/frontend/modules/pruebas/templates/procesadorSuccess.php»]
<h2>Contenido de ejemplo</h2>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum</p>
[/html]
De esta manera tenemos una action test que contiene un link que usaremos para la llamada Ajax y un DIV que usaremos para cargar el texto de respuesta. Por otro lado un action procesador que lo único que tendrá será un texto aunque perfectamente podría ejecutar una consulta a una base de datos o hacer cualquier otro tipo de acciones.
Ahora podremos probar entrar a las dos páginas y veremos en la primera el link con el DIV y en la segunda el texto que usaremos de ejemplo.
Ahora agreguemos el código JavaScript necesario en la página test para hacer que se cargue el texto de la segunda página dentro de nuestro DIV mediante Ajax.
[js highlight=»33,4,5,6,7,8,9,10,11,12,13″ htmlscript=»true» title=»Archivo: testSuccess.php»]
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery(‘#test’).click(function(){
jQuery(‘#container’).load(this.href);
return false;
});
});
</script>
<a id="test" href="<?php echo url_for(‘principal/procesador’) ?>">Cargar información</a>
<div id="container" style="border:1px solid #000;width:300px;height:300px;overflow:auto;"></div>
[/js]
Con este código le decimos exactamente lo mismo que hacíamos en los artículos de la serie de jQuery y Ajax. Cuando el document este ready se agrega un listener al link con ID=test para ser ejecutado en el evento click. En ese momento se enviará una petición Ajax al servidor y se cargará la respuesta dentro del div container. No olvidemos el return false para asegurarnos que el link finalmente no se ejecute por el flujo normal. Lo ideal luego sería una vez finalizado que separemos el código JavaScript del HTML y lo importemos mediante los archivos view.yml.
En caso de no necesitar un template para la página procesadora como ahora lo tenemos (procesadorSuccess.php), por ejemplo si necesitara enviar un XML generado para una búsqueda asíncrona, es posible decirle al action que no retorne el template utilizando return sfView::NONE
; y enviar nosotros mismos la respuesta de la siguiente manera.
[php]
public function executeProcesador(sfWebRequest $request)
{
//– Aquí podríamos ejecutar lo necesario para trabajar con la base de datos,
// archivos, arrays, lógica de negocios, etc.
$respuesta = ‘<persona><nombre>John</nombre><apellido>Doe</apellido></persona>’;
$this->getResponse()->setContent($respuesta);
return sfView::NONE;
}
[/php]
De esta manera le decimos que el contenido de respuesta es simplemente lo que enviemos mediante el método setContent() y luego que no retorne el template correspondiente.
En resumen, no hay ninguna diferencia utilizando Ajax con Symfony, simplemente entendiendo que lo que quede escrito en la página viene como respuesta de la petición ya tenemos entendido como funciona. Es interesante notar que el layout principal de la aplicación (apps/frontend/template/layout.php) no forma parte de la respuesta sino solamente el template correspondiente al action que estamos llamando asíncronamente.
Espero que haya sido de utilidad el artículo. Hasta la próxima.
Descubre más desde Neurosimbiosis
Suscríbete y recibe las últimas entradas en tu correo electrónico.
excelente articulo!
Gracias Kenny 🙂
Buenas…. mas que excelente, es un oportuno articulo, pues son cosas que no explican las paginas principales del framework… pero en fin….
Queria era hacer una pregunta referente a esto, pues comentas que:
«Por otro lado un action procesador que lo único que tendrá será un texto aunque perfectamente podría ejecutar una CONSULTA DE BASE DE DATOS o hacer cualquier otro tipo de acciones.»
Especialmente lo de la base de datos es lo que quiero saber, pues estoy usando los formularios generados por symfony 1.4 (por cierto con propel) y requiero tomar el valor de uno de esos campos para realizar una consulta a la base de datos y devolver una respuesta…. En sintesis lo que quiero es a partir de la eleccion de un campo (que es de tipo sfWidgetFormPropelChoice), poder filtrar una consulta para devolver esos datos y mostrarlo en otro campo (del mismo tipo sfWidgetFormPropelChoice)…. al elegir un cliente (campo para filtrar la consulta), se me muestran al lado (campo proyecto) los proyectos de ese cliente….
Por tanto, no se si debo pasar todo el formulario, solo ese campo, como pasar ese campo para hacer la consulta y al devolver los datos que se muestren en ese widget, y ademas saber si eso no me modifica la creacion o actualizacion (en los action new, edit, create y update) que automaticamente symfony crea….
Espero me explique bien…. gracias de todas formas
Reinaldo. Gracias por comentar.
Por un lado lo puedes hacer a mano. Crear un action «independiente» dentro de tu módulo, que reciba como parámetro el identificador del cliente, consulte a la base de datso y devuelva un XML con la información obtenida. Para esto toma en cuenta lo que explicaba hacia el final del artículo ya que no necesitas un template sino solamente la respuesta XML que será usada por el template que tiene el form:
Entonces programas JavaScript en tu template donde muestras el formulario y obtienes el evento que se disparará en el momento de selección del campo cliente, llamas al action que creaste y te devuelve la respuesta XML que la usas para cargar el campo «proyecto». Realmente esto es más programación JavaScript (jQuery) que symfony ya que esta programación está solo en el cliente.
La otra opción, aunque yo no la he probado todavía aunque parece interesante, sería utilizar algún plugin como este sfDependentSelectPlugin. Según la documentación parece muy sencillo y funciona para Doctrine y Propel.
Haz saber tu decisión y el resultado de tus pruebas y veamos como nos ayudamos a continuar 😉
Un gran abrazo.
La idea de lo que me genera dudas con respecto a usar AJAX y JQuery con lo que presente anteriormente, es que quiero al elegir el usuario el cliente (realizar todo el proceso comentado) y devolver los proyectos asociados a esa eleccion, y luego el usuario eliga el proyecto y guarde, que esto sea usando el formulario creado, no dejar de usar el $form que ya esta instanciado en el _Form.php…
eso mas que todo es lo que me interesa mantener al hacer esto….
Gracias nuevamente
Lo entiendo perfectamente Reinaldo. Y como te digo, lo podrías hacer de ambas maneras. La idea que tienes es de usar combos dependientes.
Si incluyes el plugin tendrías que sobreescribir el campo cliente y el de proyecto con el ejemplo que tienes en la dirección del plugin que te pasé. Al grabarlo se comportará normalmente. Aquí te dejo un link que muestra como personalidad formularios creados por el ORM (Doctrine o Propel)
De la misma manera si lo haces a mano con Ajax y jQuery. La respuesta XML devuelta en realidad se hará antes de grabar el registro. Sería al seleccionar un cliente, por lo que los datos quedarían ya preparados para ser grabados.
La idea con el siguiente artículo que estoy preparando es mostrar un poco la utilización de Ajax con jQuery para formularios creados a mano. Podría, si te es útil, preparar luego uno usando formularios generados por el ORM. La idea es generar contenido que sea de utilidad 🙂
Ah bueno genial lo de link, pero creo que se te olvido incorporarlo al mensaje jejeje… si puedes mandalo por favor
Perdón. Había copiado sin el link sin querer. Comentario actualizado.
Muchas gracias por el artículo.
Me gustaría saber si es posible realizar lo siguiente con una llamada ajax en symfony:
– Se modifica el contenido de un div (como en el presente articulo).
– la url pasa a ser del tipo http://misitio.es/pruebas/procesar o http://misitio.es/#prueba/procesar (con hash al estilo gmail) a fin de que un usuario pueda regresar en un futuro a este sitio directamente.
El segundo modo (empleando el #hash de la url) tengo una ligera idea de como sería posible realizarlo, pero no estoy seguro de si el otro modo es compatible con ajax.
Muchas gracias
Oscar. Buen comentario.
Si te refieres a poder usar los hash para volver en el historial del navegador usando las flechas de atrás y adelante, efectivamente sin problema lo puedes usar. jQuery por ejemplo tiene un plugin que te ayuda con eso. Y resulta muy sencillo. Yo lo probé unas veces pero con los que probé al volver solo podían hacer que los contenidos aparezcan en una sola capa. Es decir si tengo ajax para una capa1 y para una capa2 y estoy navegando el sitio al volver los contenidos aparecían todos en la capa2 por ejemplo. No recordaban la capa correspondiente. Por ahí metiéndole mano podríamos lograr eso.
Me gusta esta idea para investigar y hacer un artículo donde podamos discutir
Hola juan una pregunta respecto a lo de ajax,que no e podido encontrar en ningún lado excepto aquí información relacionada a lo que quiero.
estoy desarrollando un software de facturación con symfony y necesito que de un sfWidgetFormDoctrineChoice cargado con proveedores,al momento de elegir un proveedor,se rellenen campos como el nombre , razón social ,etc… traídos desde la base de datos.
tenia pensado lo siguiente. que de el combo box en el evento onChange() , llame a una acción y envíe el valor que se encuentra en el combo.con este valor , traer los datos de la base de datos, y pasar esos valores a un xml.
mi duda es ¿como puedo con ese xml llenar en el formulario los valores que están en blanco?
Agradecería tu respuesta.
saludos.
Fabian.
Realmente, ya la consulta que tienes no tiene nada que ver con Symfony sino con JavaScript. Con jQuery es muy sencillo.
Primero tienes que recorres el xml. Te dejo un ejemplo: http://geeks.ms/blogs/gtorres/archive/2011/01/23/leer-archivos-xml-con-jquery.aspx
Luego obtienes la referencia de tu combo y para cargarlo simplemente es así:
var p = jQuery(‘#paises’);
p.append(‘Brasil’);
p.append(‘España’);
Esto lo harías dentro de un bucle for por ejemplo y ya lo tendrás cargado. Espero que te sirva.
Excelente ejemplo, gracias!!!.
Sabras de algun ejemplo similar para symfony2
Saludos,
Hola Jesus.
Es de la misma manera. No hay diferencia alguna porque no depende del framework para nada. Tu pides una dirección URL y lo que el response te entrega es devuelto. Si sigues los demás artículos se te haría más fácil ver que siempre es lo mismo 🙂
De todas maneras pensaré en un ejemplo para levantarlo en algún artículo 😉
Yo me escribri un ejemplo loque implemente en el controller es que regrese un arreglo de objectos pasado por json_encode y en la vista/template navegarlo e imprimir el resultado, otra cosa que agregue fue especificar el content-type como application/json
Gracias por tu pronta respuesta
Saludos,
Es así mismo Jesus. Igual lo haces con la versión 1.4. Me alegro que te haya salido bien.
Excelente articulo, no sabes el tiempo que estuve buscando algo así.
una sola pregunta, no domino mucho jquery+form (html basico) . como sería realizar lo mismo pero al hacer click en el submit de un form ?
googleando encontre la respuesta. me auto respondo a continuación:
el jquery seria algo como
$(function(){
$(«#test»).submit(function(){
var queryString = $(this).serialize();
var url = $(this).attr(«action»);
$(«#container»).load(url+»?»+queryString);
return false;
});
y el input type submit
saludos
Gracias por el comentario Yigo.
Hay otro artículo que podría servirte para eso.
Hola a todos, soy nuevo en estos asuntos de symfony, estoy creando un proyecto y me gustaria saber si con jquery podría personalizar mi proyecto estilo desktop, o sea que los datos y formularios me aparezcan en ventanas, algo parecido como ZK….he buscado y realmente no he encontrado muchas cosas…de antemano les doy las gracias por cualquier ayuda que me puedan ofrecer
Hola Luis.
La verdad que el framework JavaScript que quieras usar es totalmente independiente del framework Symfony (PHP). Puedes usar el framework JavaScript que más te guste solo importando los .js necesarios.
ExtJS para mi gusto es que más se asemejaría a lo que intentas lograr.
Hola Juan, muchas gracias por tu respuesta tan rápida y eficiente, hermano, realmente me encantaron los ejemplos…a eso es a lo que me refiero…….solo me queda por preguntarte como pudiera integrarlo con Symfony, me seria de gran utilidad una guia o paginas donde pudiera encontrar ayuda sobre Symfony y EXtJS…muchas gracias hermano
Es realmente sencillo porque no tiene que ver nada con Symfony. Para incluir archivos .js o .css tienes que incluir los archivos en tu plantilla para la versión 2 o usando el view.yml si usas Symfony 1.4. Si quieres empezar con ExtJS primeramente te recomiendo usarlo con una página de prueba simple sin usar un framwork ni nada. La gran parte de aprendizaje que vas a tener más bien estará orientado a aprender a usar el ExtJS para lo cual puedes ver los ejemplos que te pasé.
Cuando entiendas como se usa incluye los archivos y lo utilizas normalmente. En el Jobeet puedes ver un ejemplo.
Gracias hermano….realmente me ha servido de gran ayuda todo lo que me has recomendado
Hola Juan Ardissone
soy yo nuevamente……es que realmente no doy al traste con esto de symfony y extjs, he descargado la version ext-4.0.2a-gpl.zip, he copiado los .js de extjs para probar al directorio web/js de mi proyecto symfony, he hecho todo lo que se me ha ocurrido y nada, ni error me da lo que hago, porque si al menos me diera algún tipo de error buscaria en base a ese error, pero ni eso……no me hace nada….hermano realmente te pido encarecidamente qe me ayudes con esto, al menos como configurar todo para que me funcione….o un ejemplo…no se con lo que puedas hermano……..de todas maneras ya me haz ayudado bastante…….muchas gracis
Hola Luis. Algunas consultas para tratar de ayudarte.
Primero, ¿Ya sabes como incluir JavaScript a tu proyecto Symfony? Creando un archivo .js cualquier con un alert(«hola mundo») ¿ya sabes como utilizarlo con Symfony? Si la respuesta es no te invitaría a leer primeramente los manuales de Symfony y empezar desde ahí. En caso de que ya lo hayas logrado,
(segunda pregunta) ¿ya sabes como utilizar ExtJS? ¿Ya haz visto la documentación del framework ExtJS como para saber cuales archivos incluir para poder trabajar?
Por último, todavía no me dijiste que versión de Symfony estás usando.
Que tal compañeros del foro, muchos saludos a tod@s..
Soy nuevo en symfony, recien llevo 2 semanas estudiando este framework y me parece bastante interesante sabiendo sacarle todo su potencial.
Tenemos hecho un sistema con symfony 1.4 que tiene dos aplicaciones backend y frontend y ahora tengo que realizar una aplicacion mobile, pero estoy tratando de hacer con lenguaje wml y el symfony parece que no reconoce ese lenguaje y no me sale nada….
Por favor ayudemen nosé como hacer… Demen algunas ideas…
Gracias y hasta pronto..
Hola Sheo en realidad esto no es un foro es un blog 🙂
Hay varios frameworks JavaScript para trabajar con aplicaciones móviles, entre ellos el jQuery mobile que use para un artículo en este blog. Sea cual sea el framework que elijas es independiente a usarlo con Symfony ya que es JavaScript. Tienes que importar los archivos Js y tus vistas usarlo con la información proveniente de tus actions.
Te recomendaría darle un vistazo primeramente a los frameworks JavaScript y luego veras que te será más fácil usarlo con Symfony.
Hola Juan, al fin he logrado incluir los archivos de Ext JS necesarios a mi proyecto symfony, … que es un Sistema de Gestión de Información, muy extenso, ya puedo mostrar ventanas etc……ahora mi gran duda, que no lo he podido lograr, es como guardar los datos de los formularios que he creado con Ext JS, siguiendo los patrones de symfony. Porque realmente no quiero migrar de un framework a otro, yo quiero seguir con Symfony, lo que con las vistas de Ext JS, no se si me hago entender.
– La versión de Symfony que uso es la 1.4.9
Bueno hermano , de antemano mucha Gracias…Saludos LUIS
Hola Juan, al fin he logrado incluir los archivos de Ext JS necesarios a mi proyecto symfony, … que es un Sistema de Gestión de Información, muy extenso, ya puedo mostrar ventanas etc……ahora mi gran duda, que no lo he podido lograr, es como guardar los datos de los formularios que he creado con Ext JS, siguiendo los patrones de symfony. Porque realmente no quiero migrar de un framework a otro, yo quiero seguir con Symfony, lo que con las vistas de Ext JS, no se si me hago entender.
– La versión de Symfony que uso es la 1.4.9
Bueno hermano , de antemano mucha Gracias…Saludos LUIS