Programmering med Yii2 Använda Ajax

Vad du ska skapa

Om du frågar, "Vad är Yii?", Kolla in Introduktion till Yii Framework, som utvärderar fördelarna med Yii och innehåller en översikt över Yii 2.0, som släpptes i oktober 2014.

I denna programmering med Yii2-serien guidar jag läsare som använder Yii2 Framework for PHP. I denna handledning undersöker vi genomförandet av interaktiva sidor med Ajax. Specifikt kommer jag att markera användningen av Ajax i två områden i mötesplaneringsprogrammet, som jag skriver parallellt med Build Your Startup-serien..

Först ska vi granska hur vi laddar in en Google Map på sidan som svar på användaren som kommer in på en viss plats. Som visas nedan, efter att jag har skrivit in Plommon Bistro och klicka på retur, kartan till höger laddas dynamiskt utan att en sida uppdateras.

För det andra visar jag dig hur vi registrerar de förändringar som en användare gör till ett möte under planeringsfasen. Mötesplanerare gör det enkelt för deltagarna att identifiera sina föredragna platser och datumstider och sedan slutligen välja den sista.

Ajax gör processen mycket enklare och snabbare, så att människor kan glida ett antal byta kontroller för att ange deras preferenser utan att någon sida uppdateras.

Bara en påminnelse, jag deltar i kommentera trådarna nedan. Jag är särskilt intresserad om du har olika tillvägagångssätt, ytterligare idéer eller vill föreslå ämnen för framtida handledning. Om du har en fråga eller ett ämne förslag, vänligen posta nedan. Du kan också nå mig på Twitter @ reifman direkt.

Använda Ajax med Yii

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

Om du bara börjar med Ajax och vill börja långsamt, har Yii Playground två enkla exempel på Ajax som kan vara till hjälp för att du ska granska. En ändrar text på en sida via Ajax, och en annan laddar svaret på en blankett på samma sida, både utan uppfriskning, och varje innehåller detaljerade kodprover.

Låt oss dyka in i våra två primära exempel. Du hittar all källa för dessa exempel i koden för mötesplaneringskod på GitHub.

Interaktiv Visar Google Maps

Bygga in formuläret

När formuläret Skapa en plats (/frontend/views/place/create_place_google.php) laddas in, innehåller den Google Places Live Search-widgeten:

Integrerar Google Places JavaScript API

Formuläret laddar Google Maps JavaScript-biblioteket och ansluter det till inmatningsfältet för plats-sökrutan:

$ gpJsLink = 'https://maps.googleapis.com/maps/api/js?' . http_build_query (array ('key' => Yii :: $ app-> params ['google_maps_key'], 'libraries' => 'platser',))); echo $ this-> registerJsFile ($ gpJsLink); $ options = '"types": ["establishment"], "componentRestrictions": "land": "oss" "; echo $ this-> registerJs ("(funktion () var input = document.getElementById (" place-searchbox "); var options = $ alternativ; searchbox = nya google.maps.places.Autocomplete (input, options); setupListeners ("place");) (); ", \ yii \ web \ Visa :: POS_END);

Delformatet _formPlaceGoogle.php innehåller några dolda fält där resultaten från kartan kan lagras innan hela sidan skickas, liksom en dold div för att visa kartan via Ajax.

använd frontend \ assets \ MapAsset; MapAsset :: register ($ this); ...      ... 

Platsen för mötesplaneraren lagrar Google-namnet, place_id, plats, webbplats, närhet och full_adress för användning under hela applikationen.

MapAsset som ingår ovan laddar in vår create_place.js-fil som fungerar mellan Google och vårt formulär; det hanterar i grund och botten sändningen och svaret på data via Ajax.

Vår Ajax hanterar JavaScript 

Jag guidar dig genom create_place.js i bitar. För det första finns det setupListeners (), kallas av förälderformuläret:

funktion setupListeners (model) // searchbox är varen för google platser objektet skapades på sidan google.maps.event.addListener (searchbox, "place_changed", function () var place = searchbox.getPlace (); if ! place.geometry) // Informera användaren om att en plats inte hittades och returnera. returnera else // migrerar JSON-data från Google till dolda formulärfält populateResult (plats, modell);); var place_input = document.getElementById (modell + '- sökrutan'); google.maps.event.addDomListener (place_input, 'keydown', funktion (e) if (e.keyCode == 13) e.preventDefault ();); 

När användaren börjar skriva, släpper widgeten ner typalternativen för realtidsplatser, och den platsändrade händelsen behandlas med varje tangenttryckning. De nyckel ner lyssnaren ovan förhindrar returnyckeln (ASCII 13 eller 0xD för dig hexeks) från att skicka in formuläret.

Så här ser det ut när du skriver. Jag går in Plommon för Plum Bistro:

Samla in den resulterande kartan och dess data

Om personen har valt anger eller klickat på en plats i rullgardinsmenyn, då populateResult () kallas; Om inte, gör vi ingenting. 

funktionen populateResult (plats, modell) // flyttar JSON data hämtas från Google till dolda formulärfält // så kan Yii2 posta data $ ('#' + modell + '- plats') .val (JSON.stringify (place [' geometri '] [' location '])); $ ( '#' + Modell + '- google_place_id) val (plats [ 'place_id']);. $ ( '#' + Modell + '- full_address) val (plats [ 'formatted_address']);. $ ( '#' + Modell + '- webbplats) val (plats [ 'hemsida']);. $ ( '#' + Modell + '- närhet) val (plats [ 'närhet']);. $ ( '#' + Modell + '- namn) val (plats [ 'name']);. loadMap (plats [ 'geometri'] [ 'lokalisering'], plats [ 'name']);  

Detta fyller alla dolda fält med data från Google och samtal loadMap () för att visa kartan:

De loadMap () funktionen är mycket specifik för Googles Plats API och visar kartan du ser ovan till höger:

funktion loadMap (gps, namn) var gps_parse = gps.toString (). ersätt ("(", "") .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 ( 'artikel') appendChild (mapcanvas).;  var latlng = nya 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.mapsMap (document.getElementById ("mapcanvas"), myOptions); var markör = ny google.maps.Marker (position: latlng, karta: karta, titel: namn); 

Användarupplevelsen är snabb och imponerande. Försök!

Dynamiskt inspelning av mötesändringar

Låt oss nu titta på hur vi registrerar ändringar i mötesplaner i realtid. Det finns inget Google API här Det är mer vanilj AJAX inom Yii Framework.

Som människor lägger till datum, tider och platser i deras mötesplaner ser du en sida så här:

De Du och Dem kolumner visar varje deltagares förmånlighet gentemot platser och datumstider. Ju större Välja skjutreglaget gör att personen kan fatta det slutliga beslutet om mötesplats och tid.

Det finns mycket data att samla in från människor, och vi vill inte kräva en sidauppdatering med varje ändring. Ajax är den perfekta lösningen för detta problem.

Jag går igenom koden för mötesplatsen ovan. Mötet-tiden panelen ovan fungerar på samma sätt.

Följer koden

På grund av MVC-ramverket och min önskan om att återanvända koddelsdelar kan flödet här vara svårt att följa. PHP-hjälparfunktioner och JavaScript måste ibland placeras i moderfiler, inte de partiklar som de var närmast relaterade till. Jag ska försöka ge dig en översikt först. Jag uppmuntrar dig att göra några passerar att läsa över det för att förstå det fullt ut. Och igen kan du bläddra i koden via GitHub.

Hint: Tänk på att filnamn för partials börjar med ett understreck.

  1. Mötesplaneringssidan laddas på /frontend/views/meeting/view.php. Den här filen innehåller även hjälpar JavaScript-funktioner för att hantera läget för knappar som Skicka och Avsluta (det vill säga efter denna ändring, kan användaren nu skicka denna inbjudan? Med mötesplaneraren måste en plats och en gång i allmänhet väljas innan den kan skickas) och visa visuella meddelanden om att ändringarna kommer att skickas till andra deltagare när användaren slutar.
  2. När du visar Var panelen för platser, laddar den /frontend/views/meeting-place/_panel.php. Den här filen innehåller hjälpar PHP-funktioner showOwnerStatus () och showParticipantStatus (), som kommer att återanvändas av sitt barn, _list.php. Men, viktigast av allt, _panel.php innehåller JavaScript-metoder för skjutreglaget Bootstrap switchChange händelse.
  3. _Panel.php-filen använder _list.php för att visa varje enskild rad för varje plats. Den här filen kommer att göra reglaget Bootstrap genom att ringa _panel.php-funktioner showOwnerStatus () och showParticipantStatus ().
  4. De switchChange funktioner kommer att göra Ajax samtal till MeetingPlaceChoiceController.php.
  5. Slutligen kallar MeetingPlaceChoiceController.php MeetingPlaceChoice.php-modellen för att spela in ändringarna i databasen.

Jag beklagar att placeringen av relevant kod är komplicerad och sprids ut. 

Nu ska jag styra dig igenom nyckelkomponenterna steg för steg.

Ajax-kod steg för steg 

Här är mötes- / view.php-rendering Meeting-Place / _panel.php. Detta visar partiet för raderna av möjliga platser och deltagarnas val:

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

Nedan är JavaScript relaterat till handlingar som svarar på Ajax-resultat men är inte direkt nödvändiga för Ajax. Du behöver inte förstå vad dessa funktioner gör för att förstå detta Ajax-exempel, men jag inkluderade dem eftersom de kallas som svar på Ajax-händelser.

id, "viewer_id": $ viewer, framgång: funktion (data) om (data) $ ('# actionSend'). removeClass ("disabled"); annars $ ('# actionSend'). addClass ("disabled"); återvänd sant; );  funktionen refreshFinalize () $ .ajax (url: '$ urlPrefix / meeting / canfinalize', data: id: $ model-> id, 'viewer_id': $ viewer data) $ ('# actionFinalize'). removeClass ("disabled"); annars $ ('# actionFinalize'). addClass ("disabled"); return true;);  JS; $ position = \ yii \ web \ Visa :: POS_READY; $ this-> registerJs ($ script, $ position); ?>

Här i mötesplatsen / _panel.php skapas tabellen som visar platser och markeringar, påpekar _list.php:

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

Ännu viktigare, det inkluderar också JavaScript nedan, som vi använder för att göra Ajax-samtal när användaren flyttar en switch, byter dess tillstånd. Knappfunktionerna motsvarar det större blåvalet, medan valfunktionerna motsvarar inställningsreglaget.

$ script = <<< JS placeCount = $placeProvider->räkna; // tillåter användaren att ställa in den slutliga platsen $ ('input [name = "place-chooser"] "). på (' switchChange.bootstrapSwitch ', funktion (e, s) // console.log (e.target. värde); // true | false // slå på mpc för användare $ .ajax (url: '$ urlPrefix / mötesplats / välj', data: id: $ model-> id, 'val': e. target.value, // e.target.value väljs MeetingPlaceChoice modell framgång: funktion (data) displayNotifier ('place'); refreshSend (); refreshFinalize (); return true;);); // användare kan säga om en plats är ett alternativ för dem $ ('input [name = "meeting-place-choice"] "). på (' switchChange.bootstrapSwitch ', funktion (e, s) // console. log (e.target.id, s); // true | false // inställt för att passera via AJAX från booleskt tillstånd om (s) state = 1; annars state = 0; $ .ajax (url: '$ urlPrefix / meeting-place-choice / set ', data: id: e.target.id,' state ': state, framgång: funktion (data) displayNotifier (' place '); refreshSend (); refreshFinalize (); returnera sant;);); JS; $ position = \ yii \ web \ Visa :: POS_READY; $ this-> registerJs ($ script, $ position); ?>

Funktionerna ovan gör samtalet till ActionSet ()MeetingPlaceChoiceController för att svara på bytet byta med Ajax-förfrågningar:

public function actionSet ($ id, $ state) Yii :: $ app-> svar-> format = \ yii \ web \ Svar :: FORMAT_JSON; // varning - inkommande AJAX-typproblem med val $ id = str_replace ('mpc -', ', $ id); // om (Yii :: $ app-> user-> getId ()! = $ mpc-> user_id ) return false, om (intval ($ state) == 0 eller $ state == 'false') $ status = MeetingPlaceChoice :: STATUS_NO; annars $ status = MeetingPlaceChoice :: STATUS_YES; // $ mpc-> spara (); MeetingPlaceChoice :: set ($ id, $ status, Yii :: $ app-> user-> getId ()); returnera $ id;

Controller-åtgärder som svarar via Ajax behöver ha ett JSON-svarformat (så här vet du att de inte är avsedda att leverera HTML):

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

Här är MeetingPlaceChoice :: set () metod som registrerar användarens handlingar i databasen och skapar en MeetingLog-post, som tittar på alla förändringar under planeringen.

statisk statisk funktionsuppsättning ($ id, $ status, $ user_id = 0, $ bulkMode = false) $ mpc = MeetingPlaceChoice :: findOne ($ id); om ($ mpc-> user_id == $ user_id) $ mpc-> status = $ status; $ Mpc-> Spara (); om (! $ bulkMode) // logga bara när inte i bulkläge, dvs acceptera alla // se setAll för mer information om ($ status == MeetingPlaceChoice :: STATUS_YES) $ command = MeetingLog :: ACTION_ACCEPT_PLACE;  annat $ command = MeetingLog :: ACTION_REJECT_PLACE;  MeetingLog :: lägg till ($ mpc-> meetingPlace-> meeting_id, $ command, $ mpc-> user_id, $ mpc-> meeting_place_id);  returnera $ mpc-> id;  annars return false; 

Funktioner relaterade till mötesändringar

I mötesplaneraren håller jag en logg över varje enskild förändring. Detta gör det möjligt för mig att veta när några minuter har gått sedan en persons senaste ändring och anmäler andra mötesdeltagare. Det är ett experiment som jag försöker med den här tjänsten, istället för att kräva att deltagarna träffar skicka varje gång de vill göra förändringar. 

Det krävs emellertid att träna dem för att förstå att det är okej att ändra det och lämna det, dvs stänga webbläsarfönstret. Så displayNotifier () funktionerna visar några blixtmeddelanden som hjälper till med det här. Jag kommer slutligen att polska dessa över tiden och ta bort dem för erfarna användare.

MeetingLog tillåter mig också att generera en textöversikt av mötesplaneringshistoriken. Om du är intresserad av att lära dig mer om det här, har jag skrivit om det i Bygg din uppstart: Meddelande om mötesändringar och leverans av meddelanden.

Vad kommer härnäst?

Jag hoppas att dessa exempel hjälper dig att förstå grunderna för Ajax i Yii. Om du är intresserad av mer avancerad Ajax planerar jag att inkludera Ajax-laddade formulär i mötesplaneringsserien. Och med tanke på att Ajax är ett område där Yii-gemenskapen inte har delat med sig många exempel. I allmänhet fungerar Ajax på samma sätt i Yii som det gör i PHP och andra ramverk, så att du kan lära av exempel från andra ramgemenskaper.

Titta på kommande tutorials i vår programmering med Yii2-serien när vi fortsätter att dyka in i olika aspekter av ramen. Du kanske också vill kolla in vår Bygga din start med PHP-serien, som använder Yii2s avancerade mall när vi bygger en verklig applikation.

Om du vill veta när nästa Yii2 handledning kommer, följ mig @ reifman på Twitter eller kolla min instruktörssida. Min instruktörssida kommer att innehålla alla artiklar från denna serie så snart de publiceras. 

relaterade länkar

  • Ajax (Wikipedia)
  • Komma igång - Ajax (Mozilla Developers Network)
  • Yii2 Developer Exchange, min Yii2 resurs webbplats