Si vous demandez "Qu'est-ce que Yii?", Consultez Introduction au framework Yii, qui passe en revue les avantages de Yii et comprend un aperçu de Yii 2.0, publié en octobre 2014.
Dans cette série de programmation avec Yii2, je guide les lecteurs dans l'utilisation du framework Yii2 pour PHP. Dans ce didacticiel, nous explorerons la mise en œuvre de pages interactives avec Ajax. Plus précisément, je vais mettre en évidence l'utilisation d'Ajax dans deux domaines de l'application Meeting Planner, sur lesquels j'écris en parallèle la série Building Your Startup..
Dans un premier temps, nous examinerons comment nous chargeons une carte Google sur la page en réponse à l’introduction par un utilisateur d’un lieu spécifique. Comme indiqué ci-dessous, après mon entrée Plum Bistro et cliquez sur Entrée, la carte de droite se charge de manière dynamique sans rafraîchissement de la page.
Deuxièmement, je vais vous montrer comment nous enregistrons les modifications apportées par un utilisateur à une réunion au cours de la phase de planification. Meeting Planner permet aux participants d'identifier facilement leurs lieux et dates préférés, puis de choisir le dernier..
Ajax rend le processus beaucoup plus facile et plus rapide, en permettant aux utilisateurs de faire glisser un certain nombre de commandes de commutateur pour indiquer leurs préférences sans actualisation de page..
Juste un rappel, je participe aux commentaires ci-dessous. Je suis particulièrement intéressé si vous avez des approches différentes, des idées supplémentaires ou si vous souhaitez suggérer des sujets pour de futurs tutoriels. Si vous avez une question ou une suggestion de sujet, veuillez poster ci-dessous. Vous pouvez également me joindre directement sur Twitter @reifman.
Si vous ne faites que commencer avec Ajax et que vous souhaitez commencer lentement, le Yii Playground propose deux exemples simples d’Ajax qu’il peut être utile de consulter. Un change le texte sur une page via Ajax, et un autre charge la réponse dans un formulaire sur la même page, les deux sans rafraîchissement, et chacun comprend des exemples de code détaillés..
Nous allons plonger dans nos deux exemples primaires. Vous pouvez trouver toutes les sources de ces exemples dans le référentiel de code de Meeting Planner à GitHub..
Lorsque le formulaire Créer un lieu (/frontend/views/place/create_place_google.php) est initialement chargé, il inclut le widget de recherche dynamique Google Adresses:
Le formulaire charge la bibliothèque JavaScript de Google Maps et la connecte au champ de saisie du lieu:
$ 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": ["établissement"], "composantRestrictions": "pays": "us"'; echo $ this-> registerJs ("(function () var input = document.getElementById ('lieu-searchbox'); var options = $ options; searchbox = new google.maps.places.Autocomplete (entrée, options); setupListeners ('place');) (); ", \ yii \ web \ View :: POS_END);
La forme partielle _formPlaceGoogle.php inclut des champs masqués dans lesquels les résultats de la carte peuvent être stockés avant que la page entière ne soit soumise, ainsi qu'un div masqué pour afficher la carte via Ajax..
utilisez frontend \ assets \ MapAsset; MapAsset :: register ($ 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 table Meeting Planner Place stocke le nom Google, le lieu_id, l'emplacement, le site Web, les environs et l'adresse complète pour une utilisation dans l'application..
Le MapAsset inclus ci-dessus charge notre fichier create_place.js qui fonctionne entre Google et notre formulaire; il gère essentiellement la transmission et la réponse des données via Ajax.
Je vais vous guider à travers create_place.js en morceaux. Tout d'abord, il y a setupListeners ()
, appelé par le formulaire parent:
function setupListeners (model) // searchbox est la var de l'objet google places créé sur la page google.maps.event.addListener (searchbox, 'lieu_changed', function () var place = searchbox.getPlace (); if ( ! place.geometry) // Informe l'utilisateur qu'un lieu n'a pas été trouvé et renvoie. return; else // migre les données JSON de Google vers des champs de formulaire masqués populateResult (lieu, modèle);); var place_input = document.getElementById (model + '- searchbox'); google.maps.event.addDomListener (place_input, 'keydown', fonction (e) if (e.keyCode == 13) e.preventDefault (););
Lorsque l'utilisateur commence à taper, le widget affiche les options de type tête de page pour les lieux réels et l'événement Place_changed est traité à chaque pression sur une touche. le touche Bas
écouteur ci-dessus empêche la clé de retour (ASCII 13 ou 0xD pour vous les geeks hexagonaux) de soumettre le formulaire.
Voici à quoi cela ressemble lorsque vous tapez. J'entre prune
pour Plum Bistro:
Si la personne a sélectionné entrer ou cliqué sur un lieu dans la liste déroulante, alors populateResult ()
est appelé; sinon on ne fait rien.
function populateResult (place, model) // déplace les données JSON extraites de Google vers des champs de formulaire masqués // afin que Yii2 puisse publier les données $ ('#' + modèle + '- location'). val (JSON.stringify (place [' géométrie '] [' emplacement '])); $ ('#' + modèle + '- google_place_id'). val (place ['place_id']); $ ('#' + model + '- full_address'). val (place ['formated_address']); $ ('#' + modèle + '- site Web'). val (lieu ['site Web']); $ ('#' + modèle + '- voisinage'). val (lieu ['voisinage']); $ ('#' + model + '- name'). val (place ['name']); loadMap (lieu ['géométrie'] ['emplacement'], lieu ['nom']);
Ceci remplit tous les champs cachés avec les données de Google et les appels loadMap ()
pour afficher la carte:
le loadMap ()
Cette fonction est très spécifique à l'API Google Place et affiche la carte que vous voyez ci-dessus à droite:
function loadMap (gps, nom) 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 noir solide'; document.querySelector ('article'). 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'expérience utilisateur est rapide et impressionnante. L'essayer!
Ensuite, voyons comment enregistrer les modifications apportées aux plans de réunion en temps réel. Il n'y a pas d'API Google ici; il est plus vanille AJAX dans le cadre Yii.
Lorsque les personnes ajoutent des dates, des heures et des lieux à leurs plans de réunion, une page comme celle-ci s'affiche:
le Vous et Leur les colonnes montrent les avantages de chaque participant pour les lieux et les dates. Le plus grand Choisir curseur permet à la personne de prendre la décision finale concernant le lieu et l'heure de la réunion.
Il y a beaucoup de données à collecter auprès des personnes, et nous ne voulons pas exiger une actualisation de la page à chaque changement. Ajax est la solution idéale à ce problème.
Je vais parcourir le code du panneau Meeting-Place ci-dessus. Le panneau Meeting-Time ci-dessus fonctionne de manière similaire.
En raison du cadre MVC et de mon désir de réutiliser des codes partiels, le flux ici peut sembler difficile à suivre. Les fonctions d'aide PHP et JavaScript devaient parfois être placés dans des fichiers parents, et non dans les partiels auxquels ils étaient le plus étroitement liés. Je vais d'abord essayer de vous donner un aperçu. Je vous encourage à faire quelques passages en le lisant pour bien le comprendre. Et encore une fois, vous pouvez parcourir le code via GitHub.
Conseil: Gardez à l'esprit que les noms de fichiers pour les partiels commencent généralement par un trait de soulignement..
showOwnerStatus ()
et showParticipantStatus ()
, qui sera réutilisé par son enfant, _list.php. Mais surtout, _panel.php inclut des méthodes JavaScript pour le curseur Bootstrap switchChange
un événement.showOwnerStatus ()
et showParticipantStatus ()
.switchChange
les fonctions effectueront des appels Ajax vers MeetingPlaceChoiceController.php.Je suis désolé, le placement du code pertinent est compliqué et étendu.
Maintenant, je vais vous guider pas à pas à travers les composants clés.
Voici Meeting / view.php rendant Meeting-Place / _panel.php. Ceci affiche le partiel des rangées de places possibles et des sélections des participants:
meeting_type == \ frontend \ models \ Meeting :: TYPE_PHONE || $ model-> meeting_type == \ frontend \ models \ Meeting :: TYPE_VIDEO)) echo $ this-> render ('… / meeting-place / _panel', ['model' => $ modèle, 'placeProvider' => $ placeProvider, 'isOwner' => $ isOwner, 'viewer' => $ viewer,]); ?>
En dessous se trouve JavaScript associé aux actions qui répondent aux résultats Ajax mais ne sont pas directement nécessaires pour Ajax. Vous n'avez pas besoin de comprendre le rôle de ces fonctions pour comprendre cet exemple Ajax, mais je les ai incluses car elles sont appelées en réponse à des événements Ajax..
id, 'viewer_id': $ viewer, succès: function (data) if (data) $ ('# actionSend'). removeClass ("disabled"); else $ ('# actionSend'). addClass ("disabled"); retourne vrai; ); function refreshFinalize () $ .ajax (url: '$ préfixe url / meeting / canfinalize' ', données: id: $ modèle-> id,' id_utilisateur ': $ spectateur, succès: fonction (données) if ( data) $ ('# actionFinalize'). removeClass ("disabled"); sinon $ ('# actionFinalize'). addClass ("disabled"); return true;); JS; $ position = \ yii \ web \ View :: POS_READY; $ this-> registerJs ($ script, $ position); ?>
Ici, dans Meeting-Place / _panel.php, le tableau indiquant les lieux et les sélections est créé, appelant _list.php:
=Yii::t('frontend','You') ?> | =Yii::t('frontend','Them') ?> | count> 1 && ($ isOwner || $ model-> meetingSettings ['participant_choose_place'])) echo Yii :: t ('frontend', 'Choose'); ?> |
Plus important encore, il inclut également le code JavaScript ci-dessous, que nous utilisons pour effectuer des appels Ajax lorsque l'utilisateur déplace un commutateur, ce qui modifie son état. Les fonctions de sélection correspondent au curseur de choix bleu le plus grand, tandis que les fonctions de choix correspondent aux curseurs de préférence.
$ script = <<< JS placeCount = $placeProvider->compter; // permet à l'utilisateur de définir le lieu final $ ('input [name = "place-chooser"] "). on (" switchChange.bootstrapSwitch ", fonction (e, s) // console.log (e.target. // true | false // active mpc pour l'utilisateur $ .ajax (url: '$ urlPrefix / meeting-place / choice', données: id: $ modèle-> id, 'val': e. target.value, // e.target.value est sélectionné Succès du modèle MeetingPlaceChoice: function (data) displayNotifier ('place'); refreshSend (); refreshFinalize (); return true;);); // les utilisateurs peuvent dire si un lieu est une option pour eux $ ('input [nom = "lieu de réunion choix"]'). on ('switchChange.bootstrapSwitch', fonction (e, s) // console. log (e.target.id, s); // true | false // définir intval pour qu'il passe via AJAX à partir de l'état booléen if (s) state = 1; sinon state = 0; $ .ajax (url: '$ urlPrefix / meeting-place-choice / set ', données: id: e.target.id,' état ': état, succès: fonction (données) displayNotifier (' lieu '); refreshSend (); refreshFinalize (); return true;);); JS; $ position = \ yii \ web \ View :: POS_READY; $ this-> registerJs ($ script, $ position); ?>
Les fonctions ci-dessus font l'appel à actionSet ()
dans MeetingPlaceChoiceController
pour répondre au changement de commutateur en utilisant des requêtes Ajax:
fonction publique actionSet ($ id, $ state) Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON; // caution - problèmes de type AJAX entrants avec val $ id = str_replace ('mpc -', ", $ id); // if (Yii :: $ app-> user-> getId ()! = $ mpc-> user_id ) renvoie false; if (intval ($ state) == 0 ou $ state == 'false') $ status = MeetingPlaceChoice :: STATUS_NO; sinon $ status = MeetingPlaceChoice :: STATUS_YES; // $ mpc-> save (); MeetingPlaceChoice :: set ($ id, $ status, Yii :: $ app-> user-> getId ()); return $ id;
Les actions du contrôleur qui répondent via Ajax doivent avoir un format de réponse JSON (de cette manière, Yii sait qu'elles ne sont pas censées fournir du code HTML):
Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON;
Ici se trouve le MeetingPlaceChoice :: set ()
méthode qui enregistre les actions de l'utilisateur dans la base de données et crée une entrée MeetingLog qui surveille toutes les modifications au cours de la planification.
ensemble de fonctions statiques publiques ($ id, $ status, $ user_id = 0, $ bulkMode = false) $ mpc = MeetingPlaceChoice :: findOne ($ id); if ($ mpc-> user_id == $ user_id) $ mpc-> status = $ status; $ mpc-> save (); if (! $ bulkMode) // ne se connecte que lorsque le mode en vrac n'est pas accepté i.e. accepte tout // voir setAll pour plus d'informations if ($ status == MeetingPlaceChoice :: STATUS_YES) $ command = MeetingLog :: ACTION_ACCEPT_PLACE; else $ command = MeetingLog :: ACTION_REJECT_PLACE; MeetingLog :: add ($ mpc-> meetingPlace-> id_reunion, $ commande, $ mpc-> id_utilisateur, $ mpc-> meeting_place_id_id); return $ mpc-> id; else return false;
Dans Meeting Planner, je conserve un journal de chaque modification. Cela me permet de savoir quand quelques minutes se sont écoulées depuis le dernier changement d'une personne et d'avertir les autres participants à la réunion. C’est une expérience que j’essaie avec ce service, au lieu d’exiger que les participants cliquent sur Soumettre chaque fois qu’ils souhaitent apporter des modifications..
Cependant, cela nécessite une formation leur permettant de comprendre qu’il est acceptable de le changer et de le laisser, c’est-à-dire de fermer la fenêtre du navigateur. Alors le displayNotifier ()
Les fonctions affichent des alertes flash pour vous aider avec ceci. Je les polirai au fil du temps et les supprimerai pour les utilisateurs expérimentés..
Le journal de réunion me permet également de générer un résumé textuel de l'historique de planification de la réunion. Si vous souhaitez en savoir plus à ce sujet, j'ai écrit à ce sujet dans Bâtir votre démarrage: informer les gens de la modification de la réunion et envoyer des notifications.
J'espère que ces exemples vous aideront à comprendre les bases de Ajax dans Yii. Si vous êtes intéressé par une version plus avancée d'Ajax, je prévois d'inclure les formulaires chargés avec Ajax dans la série Meeting Planner. Et, certes, Ajax est un domaine où la communauté Yii n’a pas donné beaucoup d’exemples. De manière générale, Ajax fonctionne de la même manière dans Yii que dans PHP et d'autres frameworks. Vous pouvez donc tirer des exemples d'autres communautés de frameworks..
Surveillez les prochains tutoriels de notre série Programmation avec Yii2 pendant que nous continuons à plonger dans différents aspects du cadre. Vous voudrez peut-être aussi consulter notre série Construire votre démarrage avec PHP, qui utilise le modèle avancé de Yii2 pour créer une application réelle.
Si vous souhaitez savoir quand le prochain tutoriel Yii2 arrive, suivez-moi @reifman sur Twitter ou consultez ma page d'instructeur. Ma page d’instructeur comprendra tous les articles de cette série dès leur publication..