Programmering med Yii2 Bruke Ajax

Hva du skal skape

Hvis du spør, "Hva er Yii?", Sjekk ut Introduksjon til Yii Framework, som vurderer fordelene med Yii og inneholder en oversikt over Yii 2.0, utgitt i oktober 2014.

I denne programmeringen med Yii2-serien, veileder jeg lesere i bruk av Yii2 Framework for PHP. I denne veiledningen vil vi utforske implementeringen av interaktive sider ved hjelp av Ajax. Spesielt skal jeg fremheve bruken av Ajax i to områder av møteplanleggerprogrammet, som jeg skriver om Bygg din oppstartsserie om parallelt.

Først vurderer vi hvordan vi laster inn et Google Map på siden som svar på at brukeren skriver inn et bestemt sted. Som vist nedenfor, etter at jeg har skrevet inn Plomme Bistro og klikk på retur, kartet til høyre laster dynamisk uten en sideoppdatering.

For det andre vil jeg vise deg hvordan vi registrerer endringene en bruker gjør til et møte i planleggingsfasen. Møtplanleggeren gjør det enkelt for deltakerne å identifisere de foretrukne stedene og datoene, og deretter til slutt velge den endelige.

Ajax gjør prosessen mye enklere og raskere, slik at folk kan skyve et antall brytere til å angi preferanser uten at siden oppdateres.

Bare en påminnelse, jeg deltar i kommentar tråder nedenfor. Jeg er spesielt interessert hvis du har forskjellige tilnærminger, flere ideer eller ønsker å foreslå emner for fremtidige opplæringsprogrammer. Hvis du har et spørsmål eller et emneforslag, vennligst legg inn under. Du kan også nå meg på Twitter @ reifman direkte.

Bruke Ajax med Yii

Av DanielSHaischt, via Wikimedia Commons, CC BY-SA 3.0

Hvis du bare begynner med Ajax og vil starte sakte, har Yii Playground to enkle eksempler på Ajax som kan være nyttig for deg å vurdere. Man endrer tekst på en side via Ajax, og en annen laster svaret på et skjema på samme side, begge uten forfriskning, og hver inneholder detaljerte kodeprøver.

La oss dykke inn i våre to primære eksempler. Du finner all kilden til disse eksemplene i Meeting Planner-kodelageret på GitHub.

Interaktiv Viser Google Maps

Bygg innmeldingsskjemaet

Når Opprett et sted-skjemaet (/frontend/views/place/create_place_google.php) i utgangspunktet laster, inkluderer det Google Places Live Search-widgeten:

Integrer Google Places API-API

Skjemaet laster Google Maps JavaScript-biblioteket og kobler det til feltet for innsatsfeltet for søkeord:

$ gpJsLink = 'https://maps.googleapis.com/maps/api/js?' . http_build_query (array ('key' => Yii :: $ app-> params ['google_maps_key'], 'biblioteker' => 'steder',))); ekko $ this-> registerJsFile ($ gpJsLink); $ options = '"types": ["establishment"], "componentRestrictions": "land": "oss"'; echo $ this-> registerJs ("(funksjon () var input = document.getElementById ('place-searchbox'); var opsjoner = $ opsjoner; searchbox = nye google.maps.places.Autocomplete (input, alternativer); setupListeners ('sted');) (); ", \ yii \ web \ Vis :: POS_END);

Delformatet _formPlaceGoogle.php inneholder noen skjulte felt der resultatene fra kartet kan lagres før hele siden er sendt, samt en skjult div for å vise kartet via Ajax.

bruk frontend \ assets \ MapAsset; MapAsset :: register ($ denne); ...      ... 

Mappeplanleggerplassertabellen lagrer Google-navnet, place_id, sted, nettsted, nærhet og fulladdress for bruk i hele programmet..

MapAsset inkludert ovenfor laster opp vår create_place.js-fil som opererer mellom Google og vårt skjema; det styrer i utgangspunktet overføring og respons av data via Ajax.

Våre Ajax Administrerer JavaScript 

Jeg veileder deg gjennom create_place.js i stykker. Først er det setupListeners (), kalt av foreldre skjemaet:

funksjon setupListeners (model) // searchbox er varen for google steder objektet opprettet på siden google.maps.event.addListener (searchbox, "place_changed", funksjon () var place = searchbox.getPlace (); if ! place.geometry) // Informer brukeren om at et sted ikke ble funnet og returnere. return; else // migrerer JSON-data fra Google til skjulte formfelt populateResult (sted, modell);); var place_input = document.getElementById (modell + '- søkeboks'); google.maps.event.addDomListener (place_input, 'keydown', funksjon (e) hvis (e.keyCode == 13) e.preventDefault ();); 

Når brukeren begynner å skrive, dråper widgeten ned typefunksjonsalternativer for virkelige steder, og stedet-endret hendelse blir behandlet med hvert tastetrykk. De keydown lytteren over forhindrer returnøkkel (ASCII 13 eller 0xD for deg hexeks) fra å sende inn skjemaet.

Slik ser det ut som du skriver. Jeg kommer inn Plomme for Plum Bistro:

Samle den resulterende kartet og dens data

Hvis personen har valgt å skrive inn eller klikket på et sted i rullegardinmenyen, så populateResult () er kalt; Hvis ikke, gjør vi ingenting. 

funksjonen populereResultat (plass, modell) // flytter JSON data henter fra Google til skjulte formfelter // så Yii2 kan legge inn data $ ('#' + modell + '-sted'). val (JSON.stringify (sted [' geometrien '] [' stedet '])); $ ( '#' + Modell + '- google_place_id') val (sted [ 'place_id']);. $ ( '#' + Modell + '- full_address') val (sted [ 'formatted_address']);. $ ( '#' + Modell + '- nettside') val (sted [ 'nettside']);. $ ( '#' + Modell + '- nærhet') val (sted [ 'nærhet']);. $ ( '#' + Modell + '- navnet') val (sted [ 'name']);. loadMap (sted [ 'geometri'] [ 'stedet'], sted [ 'navn']);  

Dette fyller alle de skjulte feltene med data fra Google og samtaler loadMap () for å vise kartet:

De loadMap () funksjonen er veldig spesifikk for Googles sted-API og viser kartet du ser over til høyre:

funksjon loadMap (gps, navn) var gps_parse = gps.toString (). erstatt ("(", "") .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 solid black'; document.querySelector ( 'artikkel') appendChild (mapcanvas.);  var latlng = nytt google.maps.LatLng (gps_lat, gps_lng); // gps ['k'], gps ['D']); var myOptions = zoom: 16, senter: latlng, mapTypeControl: false, navigationControlOptions: style: google.maps.NavigationControlStyle.SMALL, mapTypeId: google.maps.MapTypeId.ROADMAP; var map = nytt google.mapsMap (document.getElementById ("mapcanvas"), mine valg); var markør = ny google.maps.Marker (posisjon: latlng, kart: kart, tittel: navn); 

Brukeropplevelsen er rask og imponerende. Prøv det!

Dynamisk opptaksmøteendringer

La oss se på hvordan vi registrerer endringer i møteplaner i sanntid. Det er ingen Google API her Det er mer vanilje AJAX innenfor Yii Framework.

Som folk legger til datoer, tider og steder i deres møteplaner, ser du en side som dette:

De Du og Dem kolonner viser hver deltakeres gunstighet overfor steder og datatider. Jo større Velge skyveknappen gjør at personen kan ta den endelige avgjørelsen om møtested og tid.

Det er mye data å samle inn fra folk, og vi ønsker ikke å kreve en sideoppdatering med hver endring. Ajax er den ideelle løsningen for dette problemet.

Jeg vil gå gjennom koden for møtested-plasseringspanelet ovenfor. Møtestidspanelet ovenfor fungerer på samme måte.

Følger koden

På grunn av MVC-rammen og mitt ønske om å gjenbruke kodepartier, kan strømmen her føle seg vanskelig å følge. PHP-hjelperfunksjoner og JavaScript måtte noen ganger plasseres i foreldrefiler, ikke de partene de hadde mest nært knyttet til. Jeg vil prøve å gi deg en oversikt først. Jeg oppfordrer deg til å gjøre noen passerer å lese det for å forstå det fullt ut. Og igjen kan du bla gjennom koden via GitHub.

Hint: Husk at filnavn for partials vanligvis begynner med en understreking.

  1. Møterplanleggersiden er lastet på /frontend/views/meeting/view.php. Denne filen inneholder også helper JavaScript-funksjoner for å administrere tilstanden til knapper som Sende og Ferdig (det vil si etter denne endringen, kan brukeren nå sende denne invitasjonen? Med møteplanlegger må ett sted og en gang generelt velges før det kan sendes) og vise visuelle varsler om at endringene vil bli sendt til andre deltakere når brukeren fullfører.
  2. Når du viser Hvor panel for steder, det laster /frontend/views/meeting-place/_panel.php. Denne filen inneholder helper PHP-funksjoner showOwnerStatus () og showParticipantStatus (), som vil bli gjenbrukt av sitt barn, _list.php. Men viktigst av alt, _panel.php inneholder JavaScript-metoder for Bootstrap-skyveknappen switchChange begivenhet.
  3. _Panel.php-filen bruker _list.php for å vise hver enkelt rad for hvert sted. Denne filen vil gjøre skyvekontrollene for Bootstrap ved å ringe _panel.php-funksjoner showOwnerStatus () og showParticipantStatus ().
  4. De switchChange funksjoner vil gjøre Ajax samtaler til MeetingPlaceChoiceController.php.
  5. Og til slutt kaller MeetingPlaceChoiceController.php MeetingPlaceChoice.php-modellen for å registrere endringene i databasen.

Beklager, plasseringen av relevant kode er komplisert og spredt ut. 

Nå vil jeg veilede deg gjennom nøkkomponentene trinnvis.

Ajax-kode trinn for trinn 

Her møtes Meeting / view.php rendering Meeting-Place / _panel.php. Dette viser delvis for radene av mulige steder og deltakernes valg:

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

Nedenfor er JavaScript relatert til handlinger som svarer på Ajax-resultater, men er ikke direkte nødvendige for Ajax. Du trenger ikke å forstå hva disse funksjonene gjør for å forstå dette Ajax-eksempelet, men jeg inkluderte dem siden de blir kalt som svar på Ajax-hendelser.

id, 'viewer_id': $ viewer, suksess: funksjon (data) if (data) $ ('# actionSend'). removeClass ("deaktivert"); ellers $ ('# actionSend'). addClass ("deaktivert"); returnere sant; );  funksjonen refreshFinalize () $ .ajax (url: '$ urlPrefix / meeting / canfinalize', data: id: $ model-> id, 'viewer_id': $ viewer data) $ ('# actionFinalize'). removeClass ("deaktivert"); ellers $ ('# actionFinalize'). addClass ("deaktivert"); return true;);  JS; $ position = \ yii \ web \ Vis :: POS_READY; $ this-> registerJs ($ script, $ posisjon); ?>

Her i Møtested / _panel.php, opprettes tabellen som viser steder og valg, og påkaller _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', 'Velg'); ?>

Enda viktigere, det inkluderer også JavaScript nedenfor, som vi bruker til å ringe Ajax når brukeren flytter en bryter, endrer tilstanden. Koblingsfunksjonene stemmer overens med den større blåvalgregulatoren, mens valgfunksjonene stemmer overens med preferansevennene.

$ script = <<< JS placeCount = $placeProvider->telle; // lar brukeren sette det endelige stedet $ ('input [name = "place-chooser"]'). på ('switchChange.bootstrapSwitch', funksjon (e, s) // console.log (e.target. verdi); // true | false // slå på mpc for bruker $ .ajax (url: '$ urlPrefix / møteplass / velg', data: id: $ model-> id, 'val': e. target.value, // e.target.value er valgt MeetingPlaceChoice modell suksess: funksjon (data) displayNotifier ('place'); refreshSend (); refreshFinalize (); return true;);); // brukere kan si om et sted er et alternativ for dem $ ('input [name = "møteplass-valg"]'). på ('switchChange.bootstrapSwitch', funksjon (e, s) // console. logg (e.target.id, s); // true | false // sett intell for å passere via AJAX fra boolsk tilstand hvis (s) state = 1; else state = 0; $ .ajax (url: '$ urlPrefix / møte-sted-valg / sett ', data: id: e.target.id,' state ': state, suksess: funksjon (data) displayNotifier (' place '); refreshSend (); refreshFinalize (); return true;);); JS; $ position = \ yii \ web \ Vis :: POS_READY; $ this-> registerJs ($ script, $ posisjon); ?>

Funksjonene ovenfor gjør anropet til ActionSet ()MeetingPlaceChoiceController å svare på bytteendringen ved hjelp av Ajax-forespørsler:

offentlig funksjon actionSet ($ id, $ state) Yii :: $ app-> response-> format = \ yii \ web \ Svar :: FORMAT_JSON; // varsel - innkommende AJAX type problemer med val $ id = str_replace ('mpc -', ', $ id); // hvis (Yii :: $ app-> bruker-> getId ()! = $ mpc-> user_id ) return false, hvis (intval ($ state) == 0 eller $ state == 'false') $ status = MeetingPlaceChoice :: STATUS_NO; else $ status = MeetingPlaceChoice :: STATUS_YES; // $ mpc-> lagre (); MeetingPlaceChoice :: set ($ id, $ status, Yii :: $ app-> bruker-> getId ()); return $ id;

Kontrollerhandlinger som reagerer via Ajax må ha et JSON-responsformat (på denne måten Yii vet at de ikke er ment å levere HTML):

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

Her er MeetingPlaceChoice :: satt () metode, som registrerer brukerens handlinger i databasen og oppretter en MeetingLog-oppføring, som ser på alle endringene under planlegging.

statisk statisk funksjonssett ($ id, $ status, $ user_id = 0, $ bulkMode = false) $ mpc = MeetingPlaceChoice :: findOne ($ id); hvis ($ mpc-> user_id == $ user_id) $ mpc-> status = $ status; $ Mpc-> Lagre (); hvis (! $ bulkMode) // logg bare når ikke i bulkmodus dvs. godta alle // se setAll for flere detaljer hvis ($ status == MeetingPlaceChoice :: STATUS_YES) $ command = MeetingLog :: ACTION_ACCEPT_PLACE;  else $ command = MeetingLog :: ACTION_REJECT_PLACE;  MeetingLog :: legg til ($ mpc-> meetingPlace-> meeting_id, $ command, $ mpc-> user_id, $ mpc-> meeting_place_id);  returner $ mpc-> id;  ellers return false; 

Funksjoner relatert til møteendringer

I møteplanleggeren holder jeg en logg over hver eneste endring. Dette tillater meg å vite når noen få minutter har gått siden en persons siste endring og varsler andre møtedeltakere. Det er et eksperiment jeg prøver med denne tjenesten, i stedet for å kreve at deltakerne treffer send hver gang de vil foreta endring (er). 

Dette krever imidlertid å trene dem for å forstå at det er greit å endre det og la det være, dvs. lukke nettleservinduet. Så displayNotifier () Funksjoner viser noen flashvarsler for å hjelpe til med dette. Jeg vil til slutt polere disse over tid, og fjerne dem for erfarne brukere.

MeetingLog tillater meg også å generere en tekstoppsummering av møteplanleggingshistorikken. Hvis du er interessert i å lære mer om dette, har jeg skrevet om det i Bygg din oppstart: Meldende personer om møteendringer og leveringsvarsler.

Hva blir det neste?

Jeg håper disse eksemplene hjelper deg å forstå grunnleggende om Ajax i Yii. Hvis du er interessert i mer avansert Ajax, planlegger jeg å inkludere Ajax-lastede skjemaer i Meeting Planner-serien. Og admittedly, Ajax er et område der Yii-fellesskapet ikke har delt mange eksempler. Generelt fungerer Ajax på samme måte i Yii som det gjør i PHP og andre rammer, slik at du kan lære av eksempler fra andre rammemiljøer.

Se etter kommende opplæringsprogrammer i Programmering med Yii2-serien når vi fortsetter å dykke inn i ulike aspekter av rammen. Du vil kanskje også sjekke ut vårt Bygg din oppstart med PHP-serien, som bruker Yii2s avanserte mal når vi bygger en applikasjon i verden.

Hvis du vil vite når neste Yii2 opplæring kommer, følg meg @ reifman på Twitter eller sjekk min instruktørside. Min instruktørside vil inkludere alle artiklene fra denne serien så snart de er publisert. 

Relaterte linker

  • Ajax (Wikipedia)
  • Komme i gang - Ajax (Mozilla Developers Network)
  • Yii2 Developer Exchange, min Yii2 ressurs side