Programando Con Yii2 Usando Ajax

Lo que vas a crear

Si estás preguntando "¿Qué es Yii?", Echa un vistazo Introducción al marco Yii, que revisa los beneficios de Yii e incluye una descripción general de Yii 2.0, lanzada en octubre de 2014.

En esta serie de Programación con Yii2, guío a los lectores en el uso del Marco de trabajo de Yii2 para PHP. En este tutorial, exploraremos la implementación de páginas interactivas utilizando Ajax. Específicamente, voy a destacar el uso de Ajax en dos áreas de la aplicación Meeting Planner, sobre las cuales estoy escribiendo la serie Construyendo su inicio en paralelo.

Primero, revisaremos cómo cargamos un Google Map en la página en respuesta al usuario que ingresa a un lugar específico. Como se muestra abajo, después de entrar Plum Bistro y haga clic en regresar, el mapa a la derecha se carga dinámicamente sin una actualización de página.

En segundo lugar, le mostraré cómo registramos los cambios que un usuario realiza en una reunión durante la fase de planificación. El Planificador de reuniones facilita a los participantes la identificación de sus lugares y fechas preferidos y, finalmente, la elección del último.

Ajax hace que el proceso sea mucho más fácil y rápido, permitiendo a las personas deslizar una serie de controles de interruptor para indicar sus preferencias sin ninguna actualización de página.

Solo un recordatorio, participo en los hilos de comentarios a continuación. Estoy especialmente interesado si tiene diferentes enfoques, ideas adicionales o desea sugerir temas para futuros tutoriales. Si tiene alguna pregunta o sugerencia de tema, por favor publique a continuación. También puedes contactarme en Twitter @reifman directamente.

Usando Ajax Con Yii

Por DanielSHaischt, a través de Wikimedia Commons, CC BY-SA 3.0

Si recién comienza con Ajax y quiere comenzar lentamente, el Yii Playground tiene dos ejemplos simples de Ajax que pueden ser útiles para que los revise. Uno cambia el texto en una página a través de Ajax, y otro carga la respuesta a un formulario en la misma página, ambos sin actualizar, y cada uno incluye ejemplos de código detallados.

Vamos a sumergirnos en nuestros dos ejemplos principales. Puede encontrar todas las fuentes de estos ejemplos en el repositorio de códigos del organizador de reuniones en GitHub.

Visualización interactiva de Google Maps

Construyendo el formulario de entrada

Cuando se carga inicialmente el formulario Crear un lugar (/frontend/views/place/create_place_google.php), incluye el widget de búsqueda en vivo de Google Places:

Integración de la API de JavaScript de Google Places

El formulario carga la biblioteca de JavaScript de Google Maps y lo conecta al campo de entrada del cuadro de búsqueda de lugar:

$ gpJsLink = 'https://maps.googleapis.com/maps/api/js?' . http_build_query (array ('key' => Yii :: $ app-> params ['google_maps_key'], 'bibliotecas' => 'lugares',)); echo $ this-> registerJsFile ($ gpJsLink); $ options = '"types": ["establishment"], "componentRestrictions": "country": "us"'; echo $ this-> registerJs ("(function () var input = document.getElementById ('place-searchbox'); var options = $ options; searchbox = new google.maps.places.Autocomplete (entrada, opciones); setupListeners ('lugar');) (); ", \ yii \ web \ View :: POS_END);

La forma parcial de _formPlaceGoogle.php incluye algunos campos ocultos en los que se pueden almacenar los resultados del mapa antes de enviar la página completa, así como un div oculto para mostrar el mapa a través de Ajax.

utilizar frontend \ asset \ MapAsset; MapAsset :: register ($ this);…      ... 

La tabla de Meeting Planner Place almacena el nombre de Google, place_id, ubicación, sitio web, proximidad y dirección completa para su uso en toda la aplicación.

El MapAsset incluido anteriormente carga nuestro archivo create_place.js que opera entre Google y nuestro formulario; Básicamente gestiona la transmisión y respuesta de datos a través de Ajax..

Nuestro Ajax Managing JavaScript 

Te guiaré a través de create_place.js en piezas. Primero, hay setupListeners (), Llamado por el formulario padre:

function setupListeners (model) // searchbox es la var para el objeto google places creado en la página google.maps.event.addListener (searchbox, 'place_changed', function () var place = searchbox.getPlace (); if ( ! place.geometry) // Informe al usuario que no se encontró un lugar y devuelva. return; else // migra los datos JSON de Google a los campos de formulario ocultos populateResult (place, model);); var place_input = document.getElementById (model + '- searchbox'); google.maps.event.addDomListener (place_input, 'keydown', function (e) if (e.keyCode == 13) e.preventDefault ();); 

A medida que el usuario comienza a escribir, el widget despliega las opciones de typeahead para lugares del mundo real, y el evento place_changed se procesa con cada pulsación de tecla. los keydown el oyente anterior evita que la clave de retorno (ASCII 13 o 0xD para los geeks hexadecimales) envíe el formulario.

Esto es lo que parece a medida que escribe. Estoy entrando ciruela para Plum Bistro:

Recopilación del mapa resultante y sus datos

Si la persona ha seleccionado, ingrese o haga clic en un lugar en el menú desplegable, populateResult () se llama; si no, no hacemos nada. 

function populateResult (place, model) // mueve la recuperación de datos JSON de Google a los campos de formulario ocultos // para que Yii2 pueda publicar los datos $ ('#' + model + '- location'). val (JSON.stringify (place [' geometría '] [' ubicación '])); $ ('#' + model + '- google_place_id'). val (place ['place_id']); $ ('#' + model + '- full_address'). val (lugar ['formatted_address']); $ ('#' + model + '- website'). val (place ['website']); $ ('#' + modelo + '- proximidad'). val (lugar ['proximidad']); $ ('#' + model + '- name'). val (place ['name']); loadMap (place ['geometry'] ['location'], place ['name']);  

Esto llena todos los campos ocultos con datos de Google y llamadas loadMap () para visualizar el mapa:

los loadMap () La función es muy específica de la API de Google Place y muestra el mapa que se ve arriba a la derecha:

función loadMap (gps, nombre) var gps_parse = gps.toString (). replace ("(", "") .replace (")", "") .split (","); var gps_lat = parseFloat (gps_parse [0]); var gps_lng = parseFloat (gps_parse [1]); if (document.querySelector ('artículo'). children.length == 0) var mapcanvas = document.createElement ('div'); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '300px'; mapcanvas.style.width = '300px'; mapcanvas.style.border = '1px negro sólido'; document.querySelector ('artículo'). appendChild (mapcanvas);  var latlng = new google.maps.LatLng (gps_lat, gps_lng); // gps ['k'], gps ['D']); var myOptions = zoom: 16, center: latlng, mapTypeControl: false, navigationControlOptions: estilo: google.maps.NavigationControlStyle.SMALL, mapTypeId: google.maps.MapTypeId.ROADMAP; var map = new google.maps.Map (document.getElementById ("mapcanvas"), myOptions); var marker = new google.maps.Marker (position: latlng, map: map, title: name); 

La experiencia del usuario es rápida e impresionante. Intentalo!

Grabación dinámica de los cambios de la reunión

A continuación, veamos cómo registramos los cambios en los planes de reuniones en tiempo real. No hay API de Google aquí; Es más AJAX de vainilla en el marco de Yii..

A medida que las personas agregan fechas, horas y lugares a sus planes de reunión, verá una página como esta:

los y Ellos Las columnas muestran la favorabilidad de cada participante hacia los lugares y las fechas. El mas largo Escoger el control deslizante permite a la persona tomar la decisión final sobre el lugar y el horario de la reunión.

Hay una gran cantidad de datos que recopilar de las personas, y no queremos requerir una actualización de la página con cada cambio. Ajax es la solución ideal para este problema..

Recorreré el código para el panel del Lugar de Reunión arriba. El panel de reunión arriba, funciona de manera similar..

Siguiendo el código

Debido al marco MVC y mi deseo de reutilizar los códigos parciales, el flujo aquí puede parecer difícil de seguir. Las funciones de ayuda de PHP y JavaScript a veces tenían que colocarse en archivos principales, no los parciales con los que estaban más estrechamente relacionados. Trataré de darles una visión general primero. Te animo a que hagas algunos pases y lo leas para entenderlo completamente. Y nuevamente, puedes navegar el código a través de GitHub.

Sugerencia: tenga en cuenta que los nombres de archivo de los parciales generalmente comienzan con un guión bajo.

  1. La página del planificador de reuniones se carga en /frontend/views/meeting/view.php. Este archivo también incluye funciones JavaScript de ayuda para administrar el estado de los botones, como Enviar y Finalizar (es decir, después de este cambio, ¿puede el usuario enviar esta invitación ahora? Con el Planificador de reuniones, generalmente se debe seleccionar un lugar y una vez antes de poder enviarla) y mostrar notificaciones visuales de que los cambios se enviarán por correo electrónico a otros participantes cuando el usuario finalice..
  2. Al visualizar el Dónde panel para lugares, carga /frontend/views/meeting-place/_panel.php. Este archivo incluye funciones PHP de ayuda. showOwnerStatus () y showParticipantStatus (), el cual será reutilizado por su hijo, _list.php. Pero, lo más importante, _panel.php incluye métodos de JavaScript para el control deslizante Bootstrap cambiarCambiar evento.
  3. El archivo _panel.php usa _list.php para mostrar cada fila individual para cada lugar. Este archivo representará los controles deslizantes de Bootstrap llamando a las funciones _panel.php showOwnerStatus () y showParticipantStatus ().
  4. los cambiarCambiar funciones harán llamadas Ajax a MeetingPlaceChoiceController.php.
  5. Y finalmente, MeetingPlaceChoiceController.php llama al modelo MeetingPlaceChoice.php para registrar los cambios en la base de datos.

Lo siento, la colocación del código relevante es complicada y extendida.. 

Ahora, te guiaré paso a paso a través de los componentes clave..

Código Ajax Paso a Paso 

Aquí está Meeting / view.php rendering Meeting-Place / _panel.php. Esto muestra el parcial para las filas de lugares posibles y las selecciones de los participantes:

meeting_type == \ frontend \ models \ Meeting :: TYPE_PHONE || $ model-> meeting_type == \ frontend \ models \ Meeting :: TYPE_VIDEO)) echo $ this-> render ('… / meeting-place / _panel', ['model' => $ model, 'placeProvider' => $ placeProvider, 'isOwner' => $ isOwner, 'viewer' => $ viewer,]); ?> 

A continuación, se encuentra JavaScript relacionado con las acciones que responden a los resultados de Ajax pero que no son directamente necesarios para Ajax. No es necesario que entienda lo que hacen estas funciones para entender este ejemplo de Ajax, pero las incluí ya que se llaman en respuesta a los eventos de Ajax.

id, 'viewer_id': $ viewer, success: function (data) if (data) $ ('# actionSend'). removeClass ("disabled"); else $ ('# actionSend'). addClass ("disabled"); devuelve verdadero );  función refreshFinalize () $ .ajax (url: '$ urlPrefix / meeting / canfinalize', data: id: $ model-> id, 'viewer_id': $ viewer, success: function (data) if ( data) $ ('# actionFinalize'). removeClass ("disabled"); else $ ('# actionFinalize'). addClass ("disabled"); return true;);  JS; $ position = \ yii \ web \ View :: POS_READY; $ this-> registerJs ($ script, $ position); ?>

Aquí en Meeting-Place / _panel.php, se crea la tabla que muestra los lugares y las selecciones, invocando a _list.php:

  $ placeProvider, 'itemOptions' => ['class' => 'item'], 'layout' => 'items', 'itemView' => '_list', 'viewParams' => ['placeCount' => $ placeProvider-> count, 'isOwner' => $ isOwner, 'participant_choose_place' => $ model-> meetingSettings ['participant_choose_place']],])?> 
count> 1 && ($ isOwner || $ model-> meetingSettings ['participant_choose_place'])) echo Yii :: t ('frontend', 'Choose'); ?>

Más importante aún, también incluye el JavaScript a continuación, que utilizamos para hacer llamadas Ajax cuando el usuario mueve un interruptor, cambiando su estado. Las funciones de selección corresponden al control deslizante de selección azul más grande, mientras que las funciones de selección corresponden a los controles deslizantes de preferencia.

$ script = <<< JS placeCount = $placeProvider->contar; // permite al usuario establecer el lugar final $ ('input [name = "place-chooser"]'). on ('switchChange.bootstrapSwitch', function (e, s) // console.log (e.target. value); // true | false // activa mpc para el usuario $ .ajax (url: '$ urlPrefix / meeting-place / Choose', datos: id: $ model-> id, 'val': e. target.value, // e.target.value se selecciona MeetingPlaceChoice model success: function (data) displayNotifier ('place'); refreshSend (); refreshFinalize (); return true;);); // los usuarios pueden decir si un lugar es una opción para ellos $ ('input [nombre = "lugar de reunión-elección"]'). en ('switchChange.bootstrapSwitch', function (e, s) // console. log (e.target.id, s); // true | false // establece intval para pasar a través de AJAX desde el estado booleano if (s) state = 1; else state = 0; $ .ajax (url: '$ urlPrefix / meeting-place-choice / set ', data: id: e.target.id,' state ': state, success: function (data) displayNotifier (' place '); refreshSend (); refreshFinalize (); devuelve verdadero;);); JS; $ position = \ yii \ web \ View :: POS_READY; $ this-> registerJs ($ script, $ position); ?>

Las funciones anteriores hacen la llamada a actionSet () en MeetingPlaceChoiceController Para responder al cambio de cambio utilizando las solicitudes de Ajax:

función pública actionSet ($ id, $ state) Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON; // precaución: problemas de tipo AJAX entrantes con val $ id = str_replace ('mpc -', ", $ id); // if (Yii :: $ app-> user-> getId ()! = $ mpc-> user_id ) devolver falso; if (intval ($ state) == 0 o $ state == 'false') $ status = MeetingPlaceChoice :: STATUS_NO; else $ status = MeetingPlaceChoice :: STATUS_YES; // $ mpc-> save (); MeetingPlaceChoice :: set ($ id, $ status, Yii :: $ app-> user-> getId ()); return $ id;

Las acciones del controlador que responden a través de Ajax deben tener un formato de respuesta JSON (de esta manera Yii sabe que no están destinadas a entregar HTML):

Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON;

Aquí esta la MeetingPlaceChoice :: set () Método, que registra las acciones del usuario en la base de datos y crea una entrada MeetingLog, que vigila todos los cambios durante la planificación.

conjunto de funciones estáticas públicas ($ id, $ status, $ user_id = 0, $ bulkMode = false) $ mpc = MeetingPlaceChoice :: findOne ($ id); if ($ mpc-> user_id == $ user_id) $ mpc-> status = $ status; $ mpc-> save (); if (! $ bulkMode) // registrar solo cuando no esté en modo masivo, es decir, aceptar todo // ver setAll para obtener más detalles si ($ status == MeetingPlaceChoice :: STATUS_YES) $ command = MeetingLog :: ACTION_ACCEPT_PLACE;  else $ command = MeetingLog :: ACTION_REJECT_PLACE;  MeetingLog :: add ($ mpc-> meetingPlace-> meeting_id, $ command, $ mpc-> user_id, $ mpc-> meeting_place_id);  devolver $ mpc-> id;  else devolver falso; 

Características relacionadas con los cambios en la reunión

En Meeting Planner, mantengo un registro de cada cambio. Esto me permite saber cuándo han transcurrido unos minutos desde el último cambio de una persona y notificar a otros participantes de la reunión. Es un experimento que estoy probando con este servicio, en lugar de requerir que los participantes hagan clic en Enviar cada vez que quieran hacer cambios.. 

Sin embargo, esto requiere entrenarlos para que entiendan que está bien cambiarlo y dejarlo, es decir, cerrar la ventana del navegador. Entonces el displayNotifier () Las funciones muestran algunas alertas de flash para ayudar con esto: finalmente las puliré con el tiempo y las eliminaré para usuarios experimentados.

El MeetingLog también me permite generar un resumen de texto del historial de planificación de la reunión. Si está interesado en obtener más información sobre esto, lo he escrito en Cómo construir su inicio: notificar a las personas sobre los cambios en las reuniones y entregar notificaciones.

Que sigue?

Espero que estos ejemplos te ayuden a entender los conceptos básicos de Ajax en Yii. Si está interesado en un Ajax más avanzado, estoy planeando incluir formularios cargados de Ajax en la serie del Planificador de reuniones. Y, hay que reconocer que Ajax es un área donde la comunidad Yii no ha compartido muchos ejemplos. En general, Ajax funciona de manera similar en Yii como lo hace en PHP y otros marcos, por lo que puede aprender de ejemplos de otras comunidades marco..

Vea los próximos tutoriales en nuestra serie Programming With Yii2 a medida que continuamos explorando diferentes aspectos del marco. También puede consultar nuestra serie Construyendo su inicio con PHP, que utiliza la plantilla avanzada de Yii2 mientras construimos una aplicación del mundo real..

Si desea saber cuándo llegará el próximo tutorial de Yii2, síganme @reifman en Twitter o consulte la página de mi instructor. La página de mi instructor incluirá todos los artículos de esta serie tan pronto como se publiquen.. 

enlaces relacionados

  • Ajax (Wikipedia)
  • Empezando - Ajax (Red de Desarrolladores de Mozilla)
  • Yii2 Developer Exchange, mi sitio de recursos Yii2