Programmeren met Yii2 Ajax gebruiken

Wat je gaat creëren

Als je vraagt: "What's Yii?", Check out Introductie tot het Yii Framework, die de voordelen van Yii bekijkt en een overzicht van Yii 2.0 bevat, uitgebracht in oktober 2014.

In deze serie Programming With Yii2 begeleid ik lezers in gebruik van het Yii2 Framework voor PHP. In deze zelfstudie verkennen we de implementatie van interactieve pagina's met Ajax. Ik ga in het bijzonder het gebruik van Ajax benadrukken in twee delen van de applicatie Meeting Planner, die ik tegelijkertijd aan het schrijven ben over de Building Your Startup-serie..

Eerst zullen we bekijken hoe we een Google Map op de pagina laden als reactie op het invoeren van een specifieke plaats door de gebruiker. Zoals hieronder getoond, nadat ik ben binnengegaan Plum Bistro en klik op Return, de kaart naar rechts laadt dynamisch zonder een pagina te verversen.

Ten tweede zal ik u laten zien hoe we de wijzigingen registreren die een gebruiker tijdens de planningsfase maakt voor een vergadering. Meeting Planner maakt het gemakkelijk voor deelnemers om hun favoriete plaatsen en datumtijden te identificeren en uiteindelijk uiteindelijk de laatste te kiezen.

Ajax maakt het proces veel eenvoudiger en sneller, waardoor mensen een aantal schakelopties kunnen verschuiven om hun voorkeuren aan te geven zonder enige paginavernieuwing.

Ter herinnering, ik neem wel deel aan de commentaarthreads hieronder. Ik ben vooral geïnteresseerd in verschillende benaderingen, aanvullende ideeën of onderwerpen voor toekomstige zelfstudies. Als u een vraag of een suggestie voor een onderwerp heeft, kunt u hieronder berichten plaatsen. Je kunt me ook rechtstreeks op Twitter @reifman bereiken.

Ajax gebruiken met Yii

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

Als je net begint met Ajax en langzaam wilt starten, heeft de Yii Playground twee eenvoudige voorbeelden van Ajax die nuttig kunnen zijn voor jou om te beoordelen. Men verandert tekst op een pagina via Ajax, en een ander laadt het antwoord op een formulier op dezelfde pagina, beide zonder te vernieuwen, en elk bevat gedetailleerde codevoorbeelden..

Laten we een duik nemen in onze twee belangrijkste voorbeelden. Je kunt alle bronnen voor deze voorbeelden vinden in de Meeting Planner-coderepository op GitHub.

Interactief Google Maps weergeven

Het invoerformulier bouwen

Wanneer het Create a Place-formulier (/frontend/views/place/create_place_google.php) aanvankelijk wordt geladen, bevat het de live zoekwidget Google Places:

Integratie van de JavaScript-API van Google Places

Het formulier laadt de JavaScript-bibliotheek van Google Maps en verbindt het met het invoerveld plaats-zoekvak:

$ gpJsLink = 'https://maps.googleapis.com/maps/api/js?' . http_build_query (array ('key' => 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, opties); setupListeners ('plaats');) (); ", \ yii \ web \ View :: POS_END);

Het gedeeltelijke formulier _formPlaceGoogle.php bevat enkele verborgen velden waarin de resultaten van de kaart kunnen worden opgeslagen voordat de volledige pagina wordt ingediend, evenals een verborgen div om de kaart via Ajax weer te geven.

gebruik frontend \ assets \ MapAsset; MapAsset :: register ($ this); ...      ... 

De tabel Vergaderplannerplaats bevat de Google-naam, plaats_id, locatie, website, omgeving en volledig_adres voor gebruik in de hele applicatie.

De hierboven opgenomen MapAsset laadt ons create_place.js-bestand dat werkt tussen Google en ons formulier; het beheert in feite het verzenden en beantwoorden van gegevens via Ajax.

Onze Ajax Managing JavaScript 

Ik zal je door create_place.js in stukjes begeleiden. Ten eerste is dat zo setupListeners (), aangeroepen door het bovenliggende formulier:

functie setupListeners (model) // zoekveld is de var voor het google places-object gemaakt op de pagina google.maps.event.addListener (searchbox, 'place_changed', function () var place = searchbox.getPlace (); if ( ! place.geometry) // Informeer de gebruiker dat een plaats niet is gevonden en retourneer. return; else // migreert JSON-gegevens van Google naar verborgen formuliervelden populateResult (plaats, model);); var place_input = document.getElementById (model + '- searchbox'); google.maps.event.addDomListener (place_input, 'keydown', function (e) if (e.keyCode == 13) e.preventDefault ();); 

Terwijl de gebruiker begint te typen, laat de widget Typeahead-opties voor plaatsen in de echte wereld vallen en wordt de gebeurtenis place_changed verwerkt met elke druk op een toets. De toets neer De bovenstaande listener verhindert dat de return-sleutel (ASCII 13 of 0xD voor u hex-nerds) het formulier verzendt.

Dit is hoe het eruit ziet terwijl je typt. Ik ga naar binnen Pruim voor Plum Bistro:

De resulterende kaart en de bijbehorende gegevens verzamelen

Als de persoon heeft geselecteerd, voer dan in of klikte op een plaats in de vervolgkeuzelijst populateResult () wordt genoemd; zo niet, dan doen we niets. 

functie populateResult (plaats, model) // verplaatst JSON-gegevens van Google naar verborgen formuliervelden // zodat Yii2 de gegevens $ ('#' + model + '- locatie') kan plaatsen. val (JSON.stringify (plaats [' meetkunde] [locatie])); $ ( '#' + Model + '- google_place_id') val (plaats [ 'place_id']);. $ ( '#' + Model + '- full_address') val (plaats [ 'formatted_address']);. $ ( '#' + Model + '- website') val (plaats [ 'website']);. $ ( '#' + Model + '- omgeving') val (plaats [ 'omgeving']);. $ ( '#' + Model + '- de naam') val (plaats [ 'naam']);. loadMap (plaats [ 'geometrie] [locatie] plaats [ 'naam']);  

Hiermee vult u alle verborgen velden met gegevens van Google en oproepen loadMap () om de kaart weer te geven:

De loadMap () De functie is heel specifiek voor de Place API van Google en geeft de kaart weer die u hierboven rechts ziet:

functie loadMap (gps, naam) 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 effen zwart'; document.querySelector ( 'artikel') 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); 

De gebruikerservaring is snel en indrukwekkend. Probeer het!

Dynamisch opnemen van vergaderveranderingen

Laten we vervolgens kijken naar hoe we wijzigingen in vergaderplannen in realtime registreren. Er is geen Google API; het is meer vanilla AJAX binnen het Yii Framework.

Terwijl mensen datums, tijden en plaatsen aan hun vergaderplannen toevoegen, ziet u een pagina zoals deze:

De U en Hen kolommen tonen de voorkeur van elke deelnemer ten opzichte van plaatsen en datumtijden. De grotere Kiezen Met deze schuifregelaar kan de persoon de uiteindelijke beslissing nemen over de plaats en het tijdstip van de vergadering.

Er zijn veel gegevens die moeten worden verzameld van mensen en we willen niet dat een pagina wordt vernieuwd bij elke wijziging. Ajax is de ideale oplossing voor dit probleem.

Ik zal de code van het bovenstaande Meeting-Place-paneel doorlopen. Het Meeting-Time paneel hierboven werkt op dezelfde manier.

De code volgen

Vanwege het MVC-raamwerk en mijn wens om code-gedeelten opnieuw te gebruiken, kan de stroom hier moeilijk te volgen zijn. PHP-helperfuncties en JavaScript moesten soms in bovenliggende bestanden worden geplaatst, niet de gedeelten waar ze het meest aan gerelateerd waren. Ik zal eerst proberen een overzicht te geven. Ik moedig je aan om een ​​paar passen te lezen om het volledig te begrijpen. En nogmaals, je kunt de code doorbladeren via GitHub.

Tip: onthoud dat bestandsnamen voor partials meestal beginnen met een onderstrepingsteken.

  1. De pagina Meetingplanner is geladen in /frontend/views/meeting/view.php. Dit bestand bevat ook helper JavaScript-functies om de status van knoppen te beheren, zoals Sturen en Afronden (d.w.z. na deze wijziging kan de gebruiker deze uitnodiging nu verzenden? Bij Meeting Planner moet meestal één plaats en één keer worden geselecteerd voordat deze kan worden verzonden) en visuele meldingen weergeven dat de wijzigingen aan andere deelnemers worden gemaild wanneer de gebruiker klaar is.
  2. Bij het weergeven van de Waar paneel voor plaatsen, het laadt /frontend/views/meeting-place/_panel.php. Dit bestand bevat helper PHP-functies showOwnerStatus () en showParticipantStatus (), die zal worden hergebruikt door zijn kind, _list.php. Maar het belangrijkste is dat _panel.php JavaScript-methoden bevat voor de Bootstrap-schuifregelaar switchChange evenement.
  3. Het _panel.php-bestand gebruikt _list.php om elke individuele rij voor elke plaats weer te geven. Dit bestand rendert de Bootstrap-schuifregelaars door _panel.php-functies aan te roepen showOwnerStatus () en showParticipantStatus ().
  4. De switchChange functies maken Ajax-oproepen naar MeetingPlaceChoiceController.php.
  5. En ten slotte roept MeetingPlaceChoiceController.php het MeetingPlaceChoice.php-model op om de wijzigingen in de database vast te leggen.

Het spijt me dat de plaatsing van relevante code gecompliceerd en verspreid is. 

Nu zal ik u stap voor stap door de belangrijkste componenten begeleiden.

Ajax-code stap voor stap 

Hier is Meeting / view.php rendering Meeting-Place / _panel.php. Dit toont het deel voor de rijen met mogelijke plaatsen en de selecties van de deelnemers:

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,]); ?> 

Daaronder is JavaScript gerelateerd aan acties die reageren op Ajax-resultaten maar niet direct nodig zijn voor Ajax. Je hoeft niet te begrijpen wat deze functies doen om dit Ajax-voorbeeld te begrijpen, maar ik heb ze opgenomen sinds ze worden genoemd als reactie op Ajax-evenementen.

id, 'viewer_id': $ viewer, success: function (data) if (data) $ ('# actionSend'). removeClass ("disabled"); else $ ('# actionSend'). addClass ("uitgeschakeld"); geef waar terug; );  function 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, $ positie); ?>

Hier in Meeting-Place / _panel.php wordt de tabel met plaatsen en selecties gemaakt, waarbij _list.php wordt opgeroepen:

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

Wat nog belangrijker is, is dat het ook het JavaScript hieronder bevat, dat we gebruiken om Ajax-oproepen te doen wanneer de gebruiker een schakelaar verplaatst en zijn status wijzigt. De chooser-functies komen overeen met de grotere blauwe keuzeschuif, terwijl de keuzefuncties overeenkomen met de voorkeuzeschuifregelaars.

$ script = <<< JS placeCount = $placeProvider->tellen; // stelt gebruiker in staat om de laatste plaats $ ('input [name = "place-chooser"]'). on ('switchChange.bootstrapSwitch', function (e, s) // console.log (e.target. waarde); // true | false // schakel mpc in voor gebruiker $ .ajax (url: '$ urlPrefix / meeting-place / choose', data: id: $ model-> id, 'val': e. target.value, // e.target.value is geselecteerd Model succes van MeetingPlaceChoice: function (data) displayNotifier ('place'); refreshSend (); refreshFinalize (); return true;);); // gebruikers kunnen aangeven of een plaats een optie voor hen is $ ('input [name = "meeting-place-choice"]'). on ('switchChange.bootstrapSwitch', function (e, s) // console. log (e.target.id, s); // true | false // set intval om via AJAX door te geven vanuit booleaanse staat 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, $ positie); ?>

De bovenstaande functies maken de oproep naar ActionSet () in MeetingPlaceChoiceController om te reageren op de switchwijziging met Ajax-verzoeken:

public function actionSet ($ id, $ state) Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON; // caution - inkomende AJAX type problemen met val $ id = str_replace ('mpc -', ", $ id); // if (Yii :: $ app-> user-> getId ()! = $ mpc-> user_id ) return false; if (intval ($ state) == 0 of $ state == 'false') $ status = MeetingPlaceChoice :: STATUS_NO; else $ status = MeetingPlaceChoice :: STATUS_YES; // $ mpc-> save (); MeetingPlaceChoice :: set ($ id, $ status, Yii :: $ app-> gebruiker-> getId ()); return $ id;

Controlleracties die reageren via Ajax moeten een JSON-antwoordformaat hebben (op deze manier weet Yii dat het niet de bedoeling is HTML te leveren):

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

Hier is de MeetingPlaceChoice :: set () methode, die de acties van de gebruiker in de database registreert en een MeetingLog-vermelding maakt, die alle wijzigingen tijdens de planning bewaakt.

openbare statische functieset ($ id, $ status, $ user_id = 0, $ bulkMode = false) $ mpc = MeetingPlaceChoice :: findOne ($ id); if ($ mpc-> user_id == $ user_id) $ mpc-> status = $ status; $ MPC> save (); if (! $ bulkMode) // log alleen wanneer niet in bulkmodus, d.w.z. accepteer alles // zie setAll voor meer informatie 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);  return $ mpc-> id;  else return false; 

Functies die verband houden met veranderingen in vergaderingen

In Meeting Planner bewaar ik een logboek van elke wijziging. Hierdoor weet ik wanneer een paar minuten zijn verstreken sinds de laatste wijziging van een persoon en andere deelnemers aan de vergadering op de hoogte hebben gesteld. Het is een experiment dat ik met deze service probeer, in plaats van te eisen dat deelnemers elke keer dat ze een wijziging of wijzigingen willen indienen, indienen indienen. 

Dit vereist echter training ze om te begrijpen dat het goed is om het te veranderen en het te laten, d.w.z. het browservenster te sluiten. Dus de displayNotifier () functies geven een aantal flitsmeldingen weer om hiermee te helpen - ik zal deze uiteindelijk in de loop van de tijd oppoetsen en verwijderen voor ervaren gebruikers.

Met de MeetingLog kan ik ook een tekstsamenvatting van de planningsgeschiedenis van de vergadering genereren. Als u hier meer over wilt weten, heb ik erover geschreven tijdens het opbouwen van uw startup: mensen op de hoogte brengen van wijzigingen in vergaderingen en kennisgevingen afleveren.

Wat is het volgende?

Ik hoop dat deze voorbeelden je helpen de basisprincipes van Ajax in Yii te begrijpen. Als je geïnteresseerd bent in geavanceerdere Ajax, ben ik van plan om geladen Ajax-formulieren in de Meeting Planner-serie op te nemen. En toegegeven, Ajax is een gebied waar de Yii-gemeenschap niet veel voorbeelden heeft gedeeld. Over het algemeen werkt Ajax op dezelfde manier in Yii als in PHP en andere frameworks, dus je kunt leren van voorbeelden uit andere framework-communities.

Bekijk de komende tutorials in onze Programming With Yii2-serie terwijl we doorgaan met duiken in verschillende aspecten van het framework. Je kunt ook onze Building Your Startup With PHP-serie bekijken, die de geavanceerde template van Yii2 gebruikt terwijl we een real-world applicatie bouwen.

Als je wilt weten wanneer de volgende Yii2-handleiding aankomt, volg me dan @reifman op Twitter of bekijk mijn instructeurspagina. Op mijn instructeurspagina staan ​​alle artikelen uit deze serie zodra ze zijn gepubliceerd. 

Gerelateerde Links

  • Ajax (Wikipedia)
  • Aan de slag - Ajax (Mozilla Developers Network)
  • Yii2 Developer Exchange, mijn Yii2-bronsite