本教學是 Envato Tuts 上的「使用 PHP 建立您的新創公司」系列的一部分。在本系列中,我將使用我的會議規劃器應用程式作為現實生活中的範例,引導您從概念到現實啟動新創公司。在此過程中的每一步,我都會將 Meeting Planner 程式碼作為開源範例發布,您可以從中學習。我還將解決出現的與新創公司相關的業務問題。
上週,我深入研究了 Ajax,將會議安排體驗轉變為完全 ajax 化的模型,並消除了頁面刷新的需要。我大約完成了一半,主要專注於簡單的元素。
在今天的教程中,我將引導您完成更複雜的內容面板,這些面板需要更多的故障排除、研究、調試、腦力激盪和重新編碼。正如我所說,有時我想我可能不得不放棄這個功能,直到測試版發布之後。請跟著我帶您經歷那週我個人的一些惡夢(現在做得更好,不用擔心)。
我也會向您展示如何使用 Google 的 Chrome 瀏覽器開發者控制台來幫助我識別損壞的區域,這在 PHP 和 JavaScript 之間使用 Ajax 時尤其困難。就像黑暗隧道盡頭的光。
您可能已經看過我們漂亮的 Bootstrap 開關,可以幫助組織者和參與者分享他們的偏好並做出日期時間和地點的最終選擇。好吧,在 Ajax 更新後它們不應該看起來像這樣,但解決這個問題是此功能更新的一個重要部分:
如果您尚未試用會議規劃師,請繼續使用新的互動功能安排您的第一次會議。我確實參與了下面的評論主題,所以請告訴我你的想法!您也可以透過 Twitter @reifman 聯繫我。如果您想為未來的教程提出新功能或主題建議,我會特別感興趣。
#提醒一下,Meeting Planner 的所有程式碼都是用 PHP 的 Yii2 框架寫的。如果您想了解有關 Yii2 的更多信息,請查看我們的並行系列“使用 Yii2 進行編程”。
首先,讓我們看看透過 Ajax 增加會議參與者。
新增參與者的程式碼與我們先前介紹的類似。但我確實想查看稍微不同的代碼,這些代碼更新參與者列表以及顯示其身份的所有按鈕。
#以前,每次會議只有一名參與者。然後,我啟用了群組會議並建立了一個按鈕清單來指示每位參與者:
每當有參與者加入時,我都會透過 Ajax 刷新整個清單。
以下是 jQuery 函數 addParticipant()
,它會在新增每個新按鈕後呼叫 getParticipantButtons()
:
function addParticipant(id) { // ajax add participant // adding someone from new_email new_email = $('#new_email').val(); friend_id = $('#participant-email').val(); // also an email. blank before selection friend_email = $('#participant-email :selected').text(); // placeholder text before select // adding from friends if (new_email!='' && (friend_id !== undefined && friend_id!='')) { displayAlert('participantMessage','participantMessageOnlyOne'); return false; } else if (new_email!='' && new_email!==undefined) { add_email = new_email; } else if (friend_id!='') { add_email = friend_email; } else { displayAlert('participantMessage','participantMessageNoEmail'); return false; } $.ajax({ url: $('#url_prefix').val()+'/participant/add', data: { id: id, add_email:add_email, }, success: function(data) { // see remove below // to do - display acknowledgement // update participant buttons - id = meeting_id // hide panel $('#addParticipantPanel').addClass("hidden"); if (data === false) { // show error, hide tell displayAlert('participantMessage','participantMessageError'); return false; } else { // clear form $('#new_email').val(''); // odd issue with resetting the combo box $("#participant-email:selected").removeAttr("selected"); $("#participant-email").val(''); $("#participant-emailundefined").val(''); // show tell, hide error getParticipantButtons(id); displayAlert('participantMessage','participantMessageTell'); refreshSend(); refreshFinalize(); return true; } } }); }
這是 getParticipantButtons()
函數:
function getParticipantButtons(id) { $.ajax({ url: $('#url_prefix').val()+'/participant/getbuttons', data: { id: id, }, type: 'GET', success: function(data) { $('#participantButtons').html(data); }, }); }
它對 ParticipantController.php actionGetbuttons()
方法進行 Ajax 呼叫:
public function actionGetbuttons($id) { $m=Meeting::findOne($id); $participantProvider = new ActiveDataProvider([ 'query' => Participant::find()->where(['meeting_id'=>$id]), 'sort'=> ['defaultOrder' => ['participant_type'=>SORT_DESC,'status'=>SORT_ASC]], ]); $result = $this->renderPartial('_buttons', [ 'model'=>$m, 'participantProvider' => $participantProvider, ]); return $result; }
注意:我喜歡簡稱“ParCon”,而不是ParticipantController,因為它聽起來像一個遠程《星際迷航》指揮基地,或者表明我也一直在獨自開發這家初創公司長的。 我確實在 Ajax 功能上花了太多的時間。
#無論如何,上述函數會用所有更新的參與者重新填滿面板。
現在,讓我們繼續討論依賴常用的 Bootstrap 日期時間選擇器小部件之一的日期和時間。
日期、時間和地點都是ajax化中最複雜的功能。表單上使用的並不是 Bootstrap 小工具或 Google 地圖 API。結果就是 Bootstrap Switch Controllers——這些控制器沒有針對 Ajax 進行良好的設計或記錄。
以下是 Ajax 提交新增位置後損壞的開關的範例:
我將詳細介紹如何最終解決此問題,但首先讓我們來看看 meet-time/panel.php:
<?php use yii\helpers\Html; use yii\widgets\ListView; use yii\bootstrap\Collapse; use \kartik\switchinput\SwitchInput; ?> <div id="notifierTime" class="alert-info alert fade in" style="display:none;"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <?php echo Yii::t('frontend',"We'll automatically notify the organizer when you're done making changes."); ?> </div> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading" role="tab" id="headingWhen"> <div class="row"><div class="col-lg-10 col-md-10 col-xs-10"><h4 class="meeting-view"> <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseWhen" aria-expanded="true" aria-controls="collapseWhen"><?= Yii::t('frontend','When') ?></a> </h4> <span class="hint-text"> <?php if ($timeProvider->count<=1) { ?> <?= Yii::t('frontend','add one or more dates and times for participants to choose from') ?> <?php } elseif ($timeProvider->count>1) { ?> <?= Yii::t('frontend','are listed times okay?'); ?> <?php } ?> <?php if ($timeProvider->count>1 && ($model->isOrganizer() || $model->meetingSettings['participant_choose_date_time'])) { ?> <?= Yii::t('frontend','you can also choose the time') ?> <?php }?> </span></div><div class="col-lg-2 col-md-2 col-xs-2"><div style="float:right;"> <?php if ($model->isOrganizer() || $model->meetingSettings->participant_add_date_time) { ?> <?= Html::a('', 'javascript:void(0);', ['class' => 'btn btn-primary glyphicon glyphicon-plus','title'=>'Add possible times','id'=>'buttonTime','onclick'=>'showTime();']); ?> <?php } ?> </div> </div> </div> <!-- end row --> </div> <!-- end heading --> <div id="collapseWhen" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingWhen"> <div class="panel-when"> <div class="when-form hidden"> <div id="timeMessage" class="alert-info alert fade in hidden"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <span id="timeMsg1"><?= Yii::t('frontend','We\'ll automatically notify others when you\'re done making changes.')?></span> <span id="timeMsg2"><?= Yii::t('frontend','Please pick a date and time.')?></span> </div> <div id="addTime" class="hidden"> <!-- hidden add time form --> <?= $this->render('_form', [ 'model' => $meetingTime, ]) ?> </div> </div> <table class="table" id="meeting-time-list" class="hidden"> <?php if ($timeProvider->count>0): ?> <!-- Table --> <?= 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], ]) ?> <?php endif; ?> </table> </div> </div> </div>
您会注意到 timeMessage
提供预加载的警报,以便在某些 Ajax 条件下显示,正如我在上一集中回顾的那样。而且,很大程度上,代码开始遵循我在其他面板上使用的相同格式。
我尽可能地尝试以先前的方法为基础,并在ajax化每个内容面板时重用代码结构。
这是 Meeting.js 中的切换面板 JavaScript:
//show the panel function showTime() { if ($('#addTime').hasClass( "hidden")) { $('#addTime').removeClass("hidden"); $('.when-form').removeClass("hidden"); }else { $('#addTime').addClass("hidden"); $('.when-form').addClass("hidden"); } }; function cancelTime() { $('#addTime').addClass("hidden"); $('.when-form').addClass("hidden"); }
当面板出现并且用户提交新的日期时间时,它会调用 addTime()
:
function addTime(id) { start_time = $('#meetingtime-start_time').val(); start = $('#meetingtime-start').val(); if (start_time =='' || start=='') { displayAlert('timeMessage','timeMsg2'); return false; } // ajax submit subject and 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'); return true; } }); $('#addTime').addClass('hidden'); }
这会调用 MeetingTimeController.php actionAdd()
Ajax 函数:
public function 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 (empty($model->start)) { $model->start = Date('M d, Y',time()+3*24*3600); } $model->tz_current = $timezone; $model->duration = 1; $model->meeting_id= $id; $model->suggested_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; } // convert date time to timestamp $model->start = strtotime($model->start) + $selected_time['hour']*3600+ $selected_time['minute']*60; $model->end = $model->start + (3600*$model->duration); $model->save(); return true; }
当我开始通过 Ajax 添加新的日期时间或地点时,我在尝试重新初始化 Bootstrap Switch 控制器时遇到了困难,我在之前的“调度可用性和选择”一集中就开始使用该控制器。
我重新加载日期时间行,但页面上的所有开关控制器都已损坏。
问题的一部分是 Bootstrap Switch 的 Ajax 重新实例化没有详细记录。在黑暗中尝试了一些事情并在互联网上寻求帮助之后,我终于找到了解决办法。
$("input[name='meeting-time-choice']").map(function(){}
循环遍历每个开关控件,并且 $(this).bootstrapSwitch(property,value)
命令重置控件设置。花了一些时间才找到合适的控件 API。
function insertTime(id) { $.ajax({ url: $('#url_prefix').val()+'/meeting-time/inserttime', data: { id: id, }, type: 'GET', success: function(data) { $("#meeting-time-list").html(data).removeClass('hidden'); $("input[name='time-chooser']").map(function(){ //$(this).bootstrapSwitch(); $(this).bootstrapSwitch('onText','<i class="glyphicon glyphicon-ok"></i> choose'); $(this).bootstrapSwitch('offText','<i class="glyphicon glyphicon-remove"></i>'); $(this).bootstrapSwitch('onColor','success'); $(this).bootstrapSwitch('handleWidth',70); $(this).bootstrapSwitch('labelWidth',10); $(this).bootstrapSwitch('size','small'); }); $("input[name='meeting-time-choice']").map(function(){ //$(this).bootstrapSwitch(); $(this).bootstrapSwitch('onText','<i class="glyphicon glyphicon-thumbs-up"></i> yes'); $(this).bootstrapSwitch('offText','<i class="glyphicon glyphicon-thumbs-down"></i> no'); $(this).bootstrapSwitch('onColor','success'); $(this).bootstrapSwitch('offColor','danger'); $(this).bootstrapSwitch('handleWidth',50); $(this).bootstrapSwitch('labelWidth',10); $(this).bootstrapSwitch('size','small'); }); }, }); refreshSend(); refreshFinalize(); }
基本上,我必须从头开始重新配置每个控件所需的每个属性。这将上面的原始复选框转换回更丰富的开关控件。
在达到这一点之前,我在其他解决方法上浪费了很多时间。 Bootstrap Switch 是一个令人惊叹的控制器,也是 Meeting Planner 易用性的关键部分,但 ajaxifying 几乎让我崩溃。
继续,添加会议地点与添加日期和时间类似,但我想使用此内容面板来深入研究使用 Google Chrome 浏览器开发人员工具对 Ajax 进行故障排除。
正如我之前所说,在 JavaScript 和 PHP 之间调试 Ajax 可能会变得极其混乱和令人沮丧。 Ajax bug 通常很难追踪。
在这种情况下,使用 Google Chrome 浏览器的开发者控制台帮助我突破了空白。
一般来说,使用 Ajax 时,您只是遇到了故障,没有任何迹象表明出了什么问题。
以下是我用来追踪错误的 Chrome 公开的逐步可见性。
通过使用控制台选项卡,我可以看到失败的 GET 请求。这是尝试请求添加会议地点时发生的服务器错误:
这帮助我确定了通过 ajax 请求的具体参数,在本例中为会议 id = 186。
查看网络选项卡还会显示这些调用及其参数:
当您单击特定查询时,您可以看到五个选项卡;这是标题选项卡:
在本例中,预览选项卡突出显示了 Ajax 遇到的 MeetingPlaceController 中的 PHP 错误请求:
您可以看到这变得多么有用 - 特别是考虑到我必须重建大量代码才能实现所有这些调度特点。
以下是网络标签请求会议 ID = 186 地点的另一个示例:
预览标签显示所请求的视图文件不存在或至少不存在不在它应该在的地方:
Google Chrome 的开发者控制台帮助我完成了 Ajax 工作。
谢谢你,谷歌! 今天我什至不会拿我的天才模因来取笑你。
我希望您喜欢关于 Ajax 的这两集以及向快速、高效的会议安排和消除页面刷新的转变。会议安排是 Meeting Planner 的核心和灵魂,因此使其发挥出色至关重要。
我個人透過這個過程學到了很多東西,這些變化對服務產生了巨大的正面影響。
請嘗試更快速的安排並與您的朋友分享會議規劃器。像往常一樣,如果您在下面的評論中分享您的經驗,我將不勝感激,並且我始終對您的建議感興趣。您隨時可以透過 Twitter @reifman 直接與我聯繫。
我即將根據 SEC 新眾籌規則的實施與 WeFunder 啟動實驗。如果您願意,可以關注我們的個人資料。我還將在以後的教程中詳細介紹這一點。
#觀看「使用 PHP 建立您的新創公司」系列中即將推出的教學。
以上是創建您的新創公司:使用 Ajax 簡化會議安排的詳細內容。更多資訊請關注PHP中文網其他相關文章!