Se stai chiedendo "Cos'è Yii?", Dai un'occhiata Introduzione al framework Yii, che rivede i vantaggi di Yii e include una panoramica di Yii 2.0, rilasciata nell'ottobre 2014.
In questa serie di programmazione con Yii2, guido i lettori all'uso di Yii2 Framework per PHP. In questo tutorial, esploreremo l'implementazione di pagine interattive usando Ajax. In particolare, evidenzierò l'utilizzo di Ajax in due aree dell'applicazione Meeting Planner, che sto scrivendo in parallelo sulla serie Building Your Startup.
Innanzitutto, esamineremo come caricare una mappa di Google sulla pagina in risposta all'utente che inserisce un luogo specifico. Come mostrato di seguito, dopo che ho inserito Bistro Plum e fai clic su torna, la mappa a destra carica dinamicamente senza un aggiornamento della pagina.
In secondo luogo, ti mostrerò come registriamo le modifiche apportate da un utente a una riunione durante la fase di pianificazione. Meeting Planner consente ai partecipanti di identificare facilmente i loro luoghi preferiti e le loro date e, infine, di scegliere l'ultimo.
Ajax rende il processo molto più semplice e veloce, consentendo alle persone di scorrere una serie di controlli switch per indicare le loro preferenze senza alcun aggiornamento della pagina.
Solo un promemoria, parteciperò alle discussioni dei commenti qui sotto. Sono particolarmente interessato se hai approcci diversi, idee aggiuntive o vuoi suggerire argomenti per futuri tutorial. Se hai una domanda o un suggerimento sull'argomento, per favore pubblica qui sotto. Puoi anche raggiungermi su Twitter direttamente @reifman.
Se stai iniziando con Ajax e vuoi iniziare lentamente, Yii Playground ha due semplici esempi di Ajax che potrebbero essere utili per la tua revisione. Si cambia il testo su una pagina tramite Ajax e un altro carica la risposta a un modulo sulla stessa pagina, entrambi senza aggiornamento, e ciascuno include esempi di codice dettagliati.
Diamo un'occhiata ai nostri due esempi principali. Puoi trovare tutti i sorgenti per questi esempi nel repository del codice Meeting Planner su GitHub.
Quando viene caricato inizialmente il modulo Crea un luogo (/frontend/views/place/create_place_google.php), include il widget di ricerca dal vivo di Google Places:
Il modulo carica la libreria JavaScript di Google Maps e la collega al campo di inserimento place-searchbox:
$ gpJsLink = 'https://maps.googleapis.com/maps/api/js?' . http_build_query (array ('chiave' => Yii :: $ app-> params ['google_maps_key'], 'libraries' => 'places',)); 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 (input, opzioni); setupListeners ('luogo');) (); ", \ yii \ web \ View :: POS_END);
Il modulo parziale di _formPlaceGoogle.php include alcuni campi nascosti in cui è possibile memorizzare i risultati della mappa prima che venga inviata l'intera pagina, nonché un div nascosto per visualizzare la mappa tramite Ajax.
usa frontend \ assets \ MapAsset; MapAsset :: registro ($ this); ... = BaseHtml::activeHiddenInput($model, 'name'); ?> = BaseHtml::activeHiddenInput($model, 'google_place_id'); ?> = BaseHtml::activeHiddenInput($model, 'location'); ?> = BaseHtml::activeHiddenInput($model, 'website'); ?> = BaseHtml::activeHiddenInput($model, 'vicinity'); ?> = BaseHtml::activeHiddenInput($model, 'full_address'); ?>...
La tabella Place Meeting Planner memorizza il nome Google, place_id, posizione, sito web, vicinanze e indirizzo_ pieno per l'utilizzo in tutta l'applicazione.
Il MapAsset incluso sopra carica il nostro file create_place.js che opera tra Google e il nostro modulo; gestisce fondamentalmente la trasmissione e la risposta dei dati tramite Ajax.
Ti guiderò attraverso create_place.js a pezzi. Innanzitutto, c'è setupListeners ()
, chiamato dal modulo genitore:
function setupListeners (model) // searchbox è la var per l'oggetto google places creato nella pagina google.maps.event.addListener (searchbox, 'place_changed', function () var place = searchbox.getPlace (); if ( ! place.geometry) // Informa l'utente che un luogo non è stato trovato e restituisce. return; else // migra i dati JSON da Google ai campi di modulo nascosti populateResult (luogo, modello);); var place_input = document.getElementById (model + '- searchbox'); google.maps.event.addDomListener (place_input, 'keydown', function (e) if (e.keyCode == 13) e.preventDefault (););
Quando l'utente inizia a digitare, il widget abbassa le opzioni typeahead per i luoghi del mondo reale e l'evento place_changed viene elaborato con ogni pressione dei tasti. Il keydown
ascoltatore sopra impedisce la chiave di ritorno (ASCII 13 o 0xD per voi geek esadecimali) dall'invio del modulo.
Ecco come appare mentre digiti. Sto entrando prugna
per Plum Bistro:
Se la persona ha selezionato entra o ha fatto clic su un luogo nel menu a discesa, quindi populateResult ()
è chiamato; se no, non facciamo nulla.
function populateResult (luogo, modello) // sposta i dati JSON recuperati da Google nei campi dei moduli nascosti // così Yii2 può pubblicare i dati $ ('#' + modello + '- posizione'). val (JSON.stringify (luogo [' geometria '] [' location '])); $ ( '#' + Modello + '- google_place_id') val (luogo [ 'place_id']);. $ ( '#' + Modello + '- full_address') val (luogo [ 'formatted_address']);. $ ( '#' + Modello + '- sito web') val (luogo [ 'sito web']);. $ ( '#' + Modello + '- prossimita') val (luogo [ 'prossimita']);. $ ( '#' + Modello + '- il nome') val (luogo [ 'name']);. loadMap (luogo [ 'geometria'] [ 'location'], posto [ 'name']);
Questo riempie tutti i campi nascosti con i dati di Google e le chiamate loadMap ()
per visualizzare la mappa:
Il loadMap ()
la funzione è molto specifica dell'API di Google e mostra la mappa che vedi sopra a destra:
function loadMap (gps, name) 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 ('article'). children.length == 0) var mapcanvas = document.createElement ('div'); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '300px'; mapcanvas.style.width = '300px'; mapcanvas.style.border = '1px solido nero'; document.querySelector ( 'articolo') 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: style: 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);
L'esperienza dell'utente è veloce e impressionante. Provalo!
Quindi, vediamo come registriamo le modifiche ai piani di riunione in tempo reale. Non ci sono API di Google qui; è più vaniglia AJAX all'interno del framework Yii.
Mentre le persone aggiungono date, orari e luoghi ai loro piani di riunione, vedrai una pagina come questa:
Il tu e Loro le colonne mostrano la preferenza di ciascun partecipante nei confronti di luoghi e date. Il più grande Scegliere slider consente alla persona di prendere la decisione finale circa il luogo e l'orario dell'incontro.
Ci sono molti dati da raccogliere da persone e non vogliamo richiedere un aggiornamento della pagina ad ogni modifica. Ajax è la soluzione ideale per questo problema.
Passerò attraverso il codice per il pannello Luogo di incontro sopra. Il pannello Meeting-Time funziona in modo simile.
A causa del framework MVC e del mio desiderio di riutilizzare i partial parziali, il flusso qui potrebbe risultare difficile da seguire. Le funzioni helper di PHP e JavaScript dovevano a volte essere collocate nei file principali, non nei partial a cui erano più strettamente correlati. Proverò a darti una panoramica prima. Ti incoraggio a fare qualche passaggio leggendolo per capirlo appieno. E ancora, puoi sfogliare il codice tramite GitHub.
Suggerimento: tieni presente che i nomi di file per partial iniziano di solito con un carattere di sottolineatura.
showOwnerStatus ()
e showParticipantStatus ()
, che sarà riutilizzato da suo figlio, _list.php. Ma, soprattutto, _panel.php include metodi JavaScript per il cursore Bootstrap switchChange
evento.showOwnerStatus ()
e showParticipantStatus ()
.switchChange
le funzioni faranno chiamate Ajax a MeetingPlaceChoiceController.php.Mi spiace che il posizionamento del codice rilevante sia complicato e diffuso.
Ora ti guiderò attraverso i componenti chiave passo dopo passo.
Ecco il rendering Meeting / view / view.php di Meeting.php / _panel.php. Questo visualizza il partial per le file di possibili posti e le selezioni dei partecipanti:
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,]); ?>
Di seguito è riportato JavaScript relativo alle azioni che rispondono ai risultati Ajax ma che non sono direttamente necessarie per Ajax. Non hai bisogno di capire cosa fanno queste funzioni per capire questo esempio Ajax, ma li ho inclusi dal momento che sono chiamati in risposta agli eventi Ajax.
id, 'viewer_id': $ viewer, success: function (data) if (data) $ ('# actionSend'). removeClass ("disabled"); else $ ('# actionSend'). addClass ("disabled"); ritorna vero; ); function refreshFinalize () $ .ajax (url: '$ urlPrefix / meeting / canfinalize', dati: id: $ model-> id, 'viewer_id': $ viewer, success: function (data) if ( data) $ ('# actionFinalize'). removeClass ("disabled"); altrimenti $ ('# actionFinalize'). addClass ("disabled"); return true;); JS; $ position = \ yii \ web \ View :: POS_READY; $ this-> registerJs ($ script, $ position); ?>
Qui in Meeting-Place / _panel.php, viene creata la tabella che mostra i luoghi e le selezioni, invocando _list.php:
=Yii::t('frontend','You') ?> | =Yii::t('frontend','Them') ?> | conta> 1 && ($ isOwner || $ model-> meetingSettings ['participant_choose_place'])) echo Yii :: t ('frontend', 'Choose'); ?> |
Ancora più importante, include anche il JavaScript qui sotto, che usiamo per effettuare chiamate Ajax quando l'utente muove un interruttore, cambiandone lo stato. Le funzioni di selezione corrispondono al più grande cursore di scelta blu, mentre le funzioni di scelta corrispondono ai cursori delle preferenze.
$ script = <<< JS placeCount = $placeProvider->contare; // consente all'utente di impostare il luogo finale $ ('input [name = "place-chooser"]'). on ('switchChange.bootstrapSwitch', funzione (e, s) // console.log (e.target. value); // true | false // attiva mpc per l'utente $ .ajax (url: '$ urlPrefix / meeting-place / choose', dati: id: $ model-> id, 'val': e. target.value, // e.target.value è il modello di successo di MeetingPlace selezionato: function (data) displayNotifier ('place'); refreshSend (); refreshFinalize (); return true;);); // gli utenti possono dire se un posto è un'opzione per loro $ ('input [nome = "incontro-posto-scelta"]'). ('switchChange.bootstrapSwitch', funzione (e, s) // console. log (e.target.id, s); // true | false // imposta intval per passare tramite AJAX dallo stato 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 (); return true;);); JS; $ position = \ yii \ web \ View :: POS_READY; $ this-> registerJs ($ script, $ position); ?>
Le funzioni sopra riportate effettuano la chiamata a ActionSet ()
nel MeetingPlaceChoiceController
per rispondere alla modifica dello switch utilizzando le richieste Ajax:
funzione pubblica actionSet ($ id, $ state) Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON; // attenzione - problemi di tipo AJAX in entrata con val $ id = str_replace ('mpc -', ", $ id); // if (Yii :: $ app-> utente-> getId ()! = $ mpc-> user_id ) return false; 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 ()); restituisce $ id;
Le azioni dei controller che rispondono tramite Ajax devono avere un formato di risposta JSON (in questo modo Yii sa che non sono pensati per fornire HTML):
Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON;
Ecco il MeetingPlaceChoice :: set ()
metodo, che registra le azioni dell'utente nel database e crea una voce MeetingLog, che controlla tutte le modifiche durante la pianificazione.
set di funzioni statiche pubbliche ($ id, $ status, $ user_id = 0, $ bulkMode = false) $ mpc = MeetingPlaceChoice :: findOne ($ id); if ($ mpc-> user_id == $ user_id) $ mpc-> status = $ stato; $ Mpc-> save (); if (! $ bulkMode) // registra solo quando non è in modalità bulk, ad esempio, accetta tutto // vedi setAll per maggiori dettagli if ($ 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); restituisce $ mpc-> id; else return false;
In Meeting Planner, tengo un registro di ogni singolo cambiamento. Questo mi consente di sapere quando sono trascorsi alcuni minuti dall'ultima modifica di una persona e avvisare altri partecipanti alla riunione. È un esperimento che sto provando con questo servizio, invece di richiedere che i partecipanti colpiscano submit ogni volta che vogliono apportare modifiche.
Tuttavia, questo richiede un addestramento per capire che è giusto cambiarlo e lasciarlo, cioè chiudere la finestra del browser. Così la displayNotifier ()
le funzioni mostrano alcuni avvisi flash per aiutare con questo: alla fine li rifinisco nel tempo e li rimuovo per utenti esperti.
Il MeetingLog mi consente inoltre di generare un riepilogo di testo della cronologia di pianificazione della riunione. Se sei interessato a saperne di più su questo argomento, ne ho scritto in Creazione di avvio: Notifica alle persone delle modifiche alle riunioni e invio delle notifiche.
Spero che questi esempi ti aiutino a capire le basi di Ajax in Yii. Se sei interessato a Ajax più avanzato, ho intenzione di includere i moduli caricati Ajax nella serie Meeting Planner. E, certamente, l'Ajax è un'area in cui la comunità Yii non ha condiviso molti esempi. In generale, Ajax funziona in modo simile in Yii come in PHP e in altri framework, quindi puoi imparare dagli esempi di altre community framework.
Guarda le prossime esercitazioni nella nostra serie Programming With Yii2 mentre continuiamo a esplorare i diversi aspetti del framework. Potresti anche voler dare un'occhiata alla nostra serie Building Your Startup with PHP, che utilizza il template avanzato di Yii2 mentre costruiamo un'applicazione reale.
Se vuoi sapere quando arriverà il prossimo tutorial di Yii2, seguimi @reifman su Twitter o controlla la mia pagina di istruttore. La mia pagina di istruttore includerà tutti gli articoli di questa serie non appena saranno pubblicati.