Ce tutoriel fait partie de la Construire votre démarrage avec la série PHP sur Envato Tuts +. Dans cette série, je vous guide dans le lancement d’une startup du concept à la réalité en utilisant mes Planificateur de réunion application comme exemple de la vie réelle. À chaque étape du processus, je publierai le code de Meeting Planner sous forme d’exemples open source à partir desquels vous pourrez apprendre. Je traiterai également les problèmes liés au démarrage au fur et à mesure qu'ils surviennent.
La semaine dernière, j'ai approfondi ma connaissance d'Ajax pour transformer l'expérience de planification de réunion en un modèle entièrement ajaxifié et éliminer le besoin de rafraîchissements de page. Je suis arrivé à mi-chemin, en me concentrant principalement sur les éléments simples.
Dans le tutoriel d'aujourd'hui, je vais vous guider à travers les panneaux de contenu plus complexes qui nécessitaient beaucoup plus de dépannage, de recherche, de débogage, de brainstorming et de recodage. Comme je l'ai dit, il y a des moments où j'ai pensé que je devrais peut-être abandonner cette fonctionnalité jusqu'à la sortie de la version bêta. Suivez-moi pendant que je vous présente certains de mes cauchemars personnels de cette semaine (va mieux maintenant, ne t'inquiète pas).
Je vais également vous montrer comment j'ai utilisé la console de développement Google pour les navigateurs Google Chrome pour m'aider à identifier les zones brisées, ce qui peut être particulièrement difficile lorsque vous travaillez avec Ajax entre PHP et JavaScript. C'est comme la lumière au bout du tunnel des ténèbres.
Vous avez probablement déjà vu nos magnifiques commutateurs Bootstrap pour aider les organisateurs et les participants à partager leurs préférences et à choisir les dates et les lieux. Eh bien, ils ne sont pas censés ressembler à ceci après une mise à jour Ajax, mais la résolution de ce problème s'est avérée être une partie importante de cette mise à jour:
Si vous n'avez pas encore essayé Meeting Planner, planifiez votre première réunion avec les nouvelles fonctionnalités interactives. Je participe aux commentaires ci-dessous, alors dites-moi ce que vous en pensez! Vous pouvez également me joindre sur Twitter @reifman. Je suis particulièrement intéressé si vous souhaitez suggérer de nouvelles fonctionnalités ou de nouveaux sujets pour de futurs tutoriels..
Pour rappel, tout le code pour Meeting Planner est écrit dans le framework Yii2 pour PHP. Si vous souhaitez en savoir plus sur Yii2, consultez notre série parallèle Programmer avec Yii2.
Pour commencer, examinons l'ajout de participants à la réunion via Ajax..
Le code pour ajouter des participants est similaire à ce que nous avons vu précédemment. Mais je veux revoir un code légèrement différent qui met à jour la liste des participants et tous les boutons présentant leur identité..
Auparavant, il n'y avait qu'un seul participant par réunion. Ensuite, j'ai activé les réunions de groupe et créé une liste de boutons pour indiquer à chaque participant:
Chaque fois qu'un participant est ajouté, j'actualise la liste complète via Ajax.
Voici la fonction jQuery addParticipant ()
qui appelle getParticipantButtons ()
après chaque nouveau ajouté:
function addParticipant (id) // ajax add participant // ajout de quelqu'un de new_email new_email = $ ('# new_email'). val (); friend_id = $ ('# participant-email'). val (); // aussi un email. vide avant sélection friend_email = $ ('# email du participant: sélectionné'). text (); // texte de substitution avant sélection // ajout d'amis, si (new_email! = "&& (ami_id! == undefined && ami_id! =")) displayAlert ('participantMessage', 'participantMessageOnlyOne'); retourne faux; else if (new_email! = "&& new_email! == undefined) add_email = new_email; else if (ami_id! =") add_email = ami_email; else displayAlert ('participantMessage', 'participantMessageNoEmail'); retourne faux; $ .ajax (url: $ ('# url_prefix'). val () + '/ participant / add', données: id: id, add_email: add_email,, réussite: function (data) // voir supprimer ci-dessous // à faire - afficher l'accusé de réception // les boutons de mise à jour du participant - id = meeting_id // masquer le panneau $ ('# addParticipantPanel'). addClass ("hidden"); if (data === false) // show error , hide tell displayAlert ('participantMessage', 'participantMessageError'); return false; else // effacer le formulaire $ ('# new_email'). val ("); // problème étrange avec la réinitialisation de la liste déroulante $ (" # participant-email: sélectionné "). removeAttr (" sélectionné "); $ (" # participant-email "). val ("); $ ("# participant-emailundefined"). val ("); // show tell, cache erreur getParticipantButtons (id); displayAlert ('participantMessage', 'participantMessageTell'); refreshSend (); refreshFinalize (); return true;);
Ici se trouve le getParticipantButtons ()
une fonction:
fonction getParticipantButtons (id) $ .ajax (url: $ ('# url_prefix'). val () + '/ participant / getbuttons', données: id: id,, type: 'GET', réussite: fonction (data) $ ('# participantButtons'). html (data);,);
Il passe un appel Ajax à ParticipantController.php actionGetButtons ()
méthode:
fonction publique actionGetbuttons ($ id) $ m = Meeting :: findOne ($ id); $ participantProvider = new ActiveDataProvider (['query' => Participant :: find () -> où (['meeting_id' => $ id])), 'sort' => ['defaultOrder' => ['participant_type' => SORT_DESC, 'status' => SORT_ASC]],]); $ result = $ this-> renderPartial ('_ buttons', ['modèle' => $ m, 'participantProvider' => $ participantProvider,]); return $ result;
Remarque: Au lieu de ParticipantController, j'aime dire «ParCon» en abrégé car il ressemble à une base de commande Star Trek distante, ou indique que je travaille seul depuis trop longtemps sur ce démarrage.. J'ai certainement passé trop de nuits à travailler sur la fonction Ajax.
Quoi qu’il en soit, les fonctions ci-dessus repeuplent le panneau avec tous les participants mis à jour..
Passons maintenant aux dates et heures qui reposent sur l’un des widgets de sélecteur de date Bootstrap couramment utilisés..
Les dates, les heures et les lieux se sont avérés être les fonctionnalités les plus compliquées à modifier. Ce n'était pas vraiment le widget Bootstrap ou l'API Google Maps utilisé dans les formulaires. Il s’est avéré que ce sont les contrôleurs de commutateurs Bootstrap - ceux-ci n’ont pas été conçus ni documentés correctement pour Ajax..
Voici un exemple des commutateurs cassés après qu'une soumission Ajax a ajouté un lieu:
Je vais vous expliquer comment j'ai finalement résolu le problème, mais commençons par regarder le fichier meeting-time / panel.php:
= Yii::t('frontend','When') ?>
compter<=1) ?> = Yii::t('frontend','add one or more dates and times for participants to choose from') ?> compter> 1) ?> = Yii::t('frontend','are listed times okay?'); ?> nombre> 1 && ($ modèle-> isOrganizer () || $ modèle-> meetingSettings ['participant_choose_date_time'])) ?> = Yii::t('frontend','you can also choose the time') ?>isOrganizer () || $ model-> meetingSettings-> participant_add_date_time) ?> = Html::a(", 'javascript:void(0);', ['class' => 'btn btn-primaire glyphicon glyphicon-plus', 'title' => 'Ajouter des heures possibles', 'id' => 'buttonTime', 'onclick' => 'showTime ();']); ?>= Yii::t('frontend','We\'ll automatically notify others when you\'re done making changes.')?> = Yii::t('frontend','Please pick a date and time.')?>= $this->render ('_ form', ['model' => $ meetingTime,])?>compte> 0):?> = ListView::widget([ 'dataProvider' => $ timeProvider, 'itemOptions' => ['class' => 'item'], 'layout' => 'items', 'itemView' => '_list', 'viewParams' => ['timezone' => $ timezone, 'timeCount' => $ timeProvider-> count, 'isOwner' => $ isOwner, 'participant_choose_date_time' => $ model-> meetingSettings ['participant_choose_date_time'], 'whenStatus' => $ whenStatus],])? >
Vous remarquerez le timeMessage
qui fournit des alertes préchargées à afficher dans certaines conditions ajax, telles que décrites dans le dernier épisode. Et, en grande partie, le code commence à suivre les mêmes formats que ceux que j'ai utilisés sur les autres panneaux..
Autant que possible, j'ai essayé de miser sur des approches antérieures et de réutiliser la structure de code lors de l'ajaxification de chaque panneau de contenu..
Voici le code de bascule JavaScript dans Meeting.js:
// affiche la fonction du panneau showTime () if ($ ('# addTime'). hasClass ("hidden")) $ ('# addTime'). removeClass ("hidden"); $ ('. when-form'). removeClass ("hidden"); else $ ('# addTime'). addClass ("caché"); $ ('. when-form'). addClass ("caché"); ; function cancelTime () $ ('# addTime'). addClass ("caché"); $ ('. when-form'). addClass ("caché");
Lorsque le panneau apparaît et que l'utilisateur soumet une nouvelle date, il appelle Ajouter du temps()
:
fonction addTime (id) start_time = $ ('# meetingtime-start_time'). val (); start = $ ('# meetingtime-start'). val (); if (start_time == "|| start ==") displayAlert ('timeMessage', 'timeMsg2'); retourne faux; // ajax soumettre le sujet et le message $ .ajax (url: $ ('# url_prefix'). val () + '/ meeting-time / add', data: id: id, start_time: encodeURIComponent (start_time), start: encodeURIComponent (start),, success: function (data) // $ ('# meeting-note'). val ("); insertTime (id); displayAlert ('timeMessage', 'timeMsg1'); retour true;); $ ('# addTime'). addClass ('hidden');
Cela appelle le MeetingTimeController.php actionAdd ()
Fonction Ajax:
fonction publique actionAdd ($ id, $ start, $ start_time) Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON; $ timezone = MiscHelpers :: fetchUserTimezone (Yii :: $ app-> user-> getId ()); date_default_timezone_set ($ timezone); $ model = new MeetingTime (); $ model-> start = urldecode ($ start); $ model-> start_time = urldecode ($ start_time); if (vide ($ modèle-> début)) $ modèle-> début = Date ('M d, Y', heure () + 3 * 24 * 3600); $ model-> tz_current = $ timezone; $ modèle-> durée = 1; $ model-> meeting_id = $ id; $ model-> suggéré_by = Yii :: $ app-> user-> getId (); $ model-> status = MeetingTime :: STATUS_SUGGESTED; $ selected_time = date_parse ($ model-> start_time); if ($ selected_time ['hour'] === false) $ selected_time ['hour'] = 9; $ selected_time ['minute'] = 0; // convertit l'heure de la date en horodatage $ model-> start = strtotime ($ model-> start) + $ selected_time ['hour'] * 3600+ $ selected_time ['minute'] * 60; $ modèle-> fin = $ modèle-> début + (3600 * $ modèle-> durée); $ model-> save (); retourne vrai;
C'est quand j'ai commencé à ajouter de nouvelles dates ou de nouveaux lieux via Ajax que je me suis heurté à un mur qui tentait de réinitialiser le contrôleur Bootstrap Switch que j'avais commencé à utiliser dans l'épisode précédent intitulé Scheduling Availability and Choices..
Je rechargeais les rangées de dates et tous les contrôleurs de commutateurs de la page étaient cassés..
Une partie du problème était que la ré-instanciation Ajax pour le commutateur Bootstrap n'était pas bien documentée. Après avoir essayé une poignée de choses dans le noir et cherché de l’aide sur les interwebs, j’ai finalement trouvé le moyen.
le $ ("input [nom = 'choix-heure-de-réunion']"). map (fonction ()
boucles à travers chaque commande de commutateur, et l'ensemble de $ (this) .bootstrapSwitch (propriété, valeur)
Les commandes réinitialisent les paramètres de contrôle. Il a fallu un certain temps pour découvrir l’API de contrôle appropriée.
function insertTime (id) $ .ajax (url: $ ('# url_prefix'). val () + '/ meeting-time / inserttime', données: id: id,, tapez: 'GET', succès : function (data) $ ("# liste-heure-réunion"). html (data) .removeClass ('caché'); $ ("input [nom = 'sélecteur de temps']"). map (fonction ( ) // $ (this) .bootstrapSwitch (); $ (this) .bootstrapSwitch ('onText', ' choisir'); $ (this) .bootstrapSwitch ('offText', ''); $ (this) .bootstrapSwitch ('onColor', 'success'); $ (this) .bootstrapSwitch ('handleWidth', 70); $ (this) .bootstrapSwitch ('labelWidth', 10); $ (this) .bootstrapSwitch ('taille', 'petit'); ); $ ("input [name = 'meeting-time-choice']"). map (function () // $ (this) .bootstrapSwitch (); $ (this) .bootstrapSwitch ('onText', ' Oui'); $ (this) .bootstrapSwitch ('offText', ' non'); $ (this) .bootstrapSwitch ('onColor', 'success'); $ (this) .bootstrapSwitch ('offColor', 'danger'); $ (this) .bootstrapSwitch ('handleWidth', 50); $ (this) .bootstrapSwitch ('labelWidth', 10); $ (this) .bootstrapSwitch ('taille', 'petit'); ); ,); refreshSend (); refreshFinalize ();
En gros, je devais reconfigurer chaque propriété dont j'avais besoin pour chaque contrôle à partir de zéro. Cela a transformé les cases à cocher brutes ci-dessus dans les contrôles de commutateur plus riches.
Avant d’atteindre ce stade, j’ai perdu beaucoup de temps dans d’autres solutions de contournement. Bootstrap Switch est un contrôleur incroyable et un élément clé de la facilité d'utilisation de Meeting Planner - mais ajaxifier m'a presque zappé.
Ajouter des lieux de réunion était similaire à ajouter des dates et des heures, mais j'aimerais utiliser ce panneau de contenu pour plonger dans le dépannage d'Ajax avec les outils de développement du navigateur de Google Chrome..
Comme je le disais plus tôt, le débogage Ajax entre JavaScript et PHP peut être extrêmement déroutant et frustrant. Les bugs Ajax sont souvent difficiles à détecter.
Dans ce cas, l’utilisation de la console de développement du navigateur Google Chrome m’a aidé à surmonter le vide.
Généralement avec Ajax, vous avez juste un dysfonctionnement sans aucune indication de ce qui a mal tourné.
Voici, étape par étape, une partie de la visibilité offerte par Chrome que j'ai utilisée pour localiser les erreurs..
En utilisant le Console onglet, je pouvais voir les demandes GET échouées. Il s'agit d'une erreur de serveur qui tente de demander l'ajout d'un lieu à une réunion:
Cela m'a aidé à identifier les arguments spécifiques demandés via ajax, dans ce cas, pour la réunion id = 186.
En regardant le Réseau Onglet affiche également ces appels et leurs arguments:
Lorsque vous cliquez sur la requête spécifique, vous pouvez voir cinq onglets; Ici se trouve le En-têtes languette:
Dans ce cas, le Aperçu Onglet mis en évidence mon erreur PHP dans le MeetingPlaceController rencontré par la demande Ajax:
Vous pouvez voir à quel point cela devient utile, en particulier compte tenu de l'étendue du code que j'ai dû reconstruire pour ajuster toutes ces fonctionnalités de planification..
Voici un autre exemple de la Réseau onglet demandant des places pour l'id de la réunion = 186:
le Aperçu onglet a montré que le fichier de vue demandé n’existait pas ou du moins n’était pas là où il devrait être:
La console pour développeurs de Google Chrome m'a beaucoup aidé à terminer le travail sur Ajax..
Merci Google! Je ne vais même pas te taquiner à propos de mon génie aujourd'hui.
J'espère que vous avez apprécié ces deux épisodes sur Ajax, ainsi que la transformation en planification de réunion rapide et efficace et l'élimination des actualisations de page. La planification des réunions est le cœur et l'âme de Meeting Planner. Il est donc essentiel qu'il fonctionne parfaitement..
J'ai personnellement beaucoup appris grâce à ce processus et les changements ont eu un impact positif spectaculaire sur le service..
Essayez la planification plus rapide et partagez Meeting Planner avec vos amis. Comme d'habitude, j'apprécierais que vous partagiez votre expérience ci-dessous dans les commentaires, et je suis toujours intéressé par vos suggestions. Vous pouvez toujours me joindre directement sur Twitter @reifman.
Je me rapproche du lancement de l'expérience avec WeFunder basée sur la mise en œuvre des nouvelles règles de la SEC en matière de financement participatif. Vous pouvez suivre notre profil ici si vous le souhaitez. Je vais aussi écrire plus à ce sujet dans un prochain tutoriel.
Surveillez les prochains tutoriels de la série Construire votre démarrage avec PHP.