• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用PHP构建:会议时间和地点的 Ajax

Planner 应用程序作为现实生活中的示例,指导您从概念到现实启动一家初创公司 。在此过程中的每一步,我都会将 Meeting Planner 代码作为开源示例发布,您可以从中学习。我还将解决与启动相关的业务问题。

深入了解 ajax 

上周,我深入研究了 Ajax,将会议安排体验转变为完全 ajax 化的模型,并消除了页面刷新的需要。我大约完成了一半,主要关注简单的元素。

在今天的教程中,我将指导您完成更复杂的内容面板,这些面板需要更多的故障排除、研究、调试、头脑风暴和重新编码。正如我所说,有时我认为我可能不得不放弃这个功能,直到测试版发布之后。跟随我从那周开始我的一些个人噩梦(现在做得更好,别担心)。

我还将向您展示我如何使用 Google 的 chrome 浏览器开发人员控制台来帮助我识别损坏的区域 — 当在 phpjavascript之间使用 Ajax 时,这尤其困难。这就像黑暗隧道尽头的光。

您可能已经看过我们漂亮的 Bootstrap 开关,可帮助组织者和参与者分享他们的偏好,并为日期时间和地点做出最终选择。好吧,在 Ajax 更新后它们不应该是这样的——但是解决这个问题是这个特性更新的重要组成部分:

使用PHP构建:会议时间和地点的 Ajax  第1张

如果您尚未试用 Meeting Planner,请继续  使用新的交互式功能安排您的第一次会议。我确实参与了下面的评论线程,所以告诉我你的想法!你也可以在 Twitter @reifman 上联系我。如果您想为未来的教程推荐新功能或主题,我特别感兴趣。

提醒一下,Meeting Planner 的所有代码都是用 PHP 的 Yii2 F ram ework 编写的。如果您想了解更多关于 Yii2 的信息,请查看我们的并行系列 Programming With Yii2。

首先,让我们看一下通过 Ajax 添加会议参与者。

添加会议参与者

使用PHP构建:会议时间和地点的 Ajax  第2张

添加参与者的代码与我们之前介绍的类似。但我确实想查看稍微不同的代码,这些代码会更新参与者列表和所有显示其身份的按钮。

以前,每次会议只有一名参与者。然后,我 启用了小组会议并创建了一个按钮列表来指示每个参与者:

使用PHP构建:会议时间和地点的 Ajax  第3张

每当添加参与者时,我都会通过 Ajax 刷新整个列表。

 这是在添加每个新函数后addParticipant() 调用的 jquery 函数: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 方法进行 Ajax 调用actionGetbuttons():

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 日期时间选择器小部件之一的日期和时间。

添加日期和时间

使用PHP构建:会议时间和地点的 Ajax  第4张

日期、时间和地点都被证明是 ajaxify 最复杂的特征。与其说是表单上使用的 Bootstrap 小部件或 Google Maps api 。结果证明是Bootstrap Switch Controllers ——这些都不是为 Ajax 设计或记录的。

通过 Ajax 的引导开关控制器的问题

以下是 Ajax 提交添加地点后的损坏开关示例:

使用PHP构建:会议时间和地点的 Ajax  第5张

我将介绍我最终是如何解决这个问题的,但首先,让我们看一下 meeting-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">&times;</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">&times;</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>&nbsp;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>&nbsp;yes');
          $(this).bootstrapSwitch('offText','<i class="glyphicon glyphicon-thumbs-down"></i>&nbsp;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 进行故障排除。

添加会议地点

使用PHP构建:会议时间和地点的 Ajax  第6张

正如我之前所说,在 JavaScript 和 PHP 之间调试 Ajax 会变得非常混乱和令人沮丧。Ajax 错误通常很难追踪。

在这种情况下,使用谷歌 Chrome 浏览器的开发者控制台帮助我突破了空白。

一般来说,使用 Ajax,您只会出现功能障碍,而没有任何迹象表明出了什么问题。

以下是我用来追踪错误的 Chrome 公开的一些可见性的逐步说明。

通过使用控制台选项卡,我可以看到失败的 GET 请求。这是尝试请求将地点添加到会议的服务器错误:

使用PHP构建:会议时间和地点的 Ajax  第7张

这帮助我确定了通过 ajax 请求的特定参数,在本例中为会议 id = 186。

查看Network选项卡还会显示这些调用及其参数:

使用PHP构建:会议时间和地点的 Ajax  第8张

当您点击具体查询时,您可以看到五个选项卡;这是标题选项卡:

使用PHP构建:会议时间和地点的 Ajax  第9张

在这种情况下, 预览选项卡突出显示了 Ajax 请求遇到的 MeetingPlaceController 中的 PHP 错误:

使用PHP构建:会议时间和地点的 Ajax  第10张

您可以看到这变得多么有用——尤其是考虑到我必须重新构建大量代码以 ajaxify 所有这些调度功能。

这是请求会议 id = 186 的地点的网络选项卡的另一个示例 :

使用PHP构建:会议时间和地点的 Ajax  第11张

Preview 选项卡显示请求的 视图文件不存在或至少不在应有的位置:

使用PHP构建:会议时间和地点的 Ajax  第12张

Google Chrome 的开发者控制台帮助我完成了 Ajax 工作。

谢谢你,谷歌!今天我什至不会拿我的天才模因取笑你。 

下一步是什么?

我希望您喜欢这些关于 Ajax 的章节,以及向快速、高效的会议安排和消除页面刷新的转变。会议安排是 Meeting Planner 的核心和灵魂,因此让它发挥作用至关重要。


文章目录
  • 深入了解 ajax
  • 添加会议参与者
    • 添加日期和时间
      • 通过 Ajax 的引导开关控制器的问题
    • 添加会议地点
  • 下一步是什么?