建立您的初创企业:为提醒做准备

最终产品图片
您将要创造的

本教程是Envato Tuts +上的“ 使用PHP构建启动”系列的一部分。 在本系列文章中,我将以我的Meeting Planner应用程序作为真实示例,指导您完成从概念到现实的启动。 在此过程的每一步中,我都会将Meeting Planner代码作为开放源代码示例发布,您可以从中学习。 我还将解决与启动相关的业务问题。

在这个由两部分组成的系列文章中,我将描述我们如何构建用于提醒及其传递的基础结构。 本集将重点介绍配置提醒后的基础架构和用户体验。

如果您尚未尝试使用会议计划器,请继续并安排您的第一次会议 。 我确实参与了下面的评论主题,所以请告诉我您的想法! 如果您想要新功能或为以后的教程提出建议,我特别感兴趣。

提醒一下,Meeting Planner的所有代码都是在PHP的Yii2框架中编写的。 如果您想了解有关Yii2的更多信息,请查看我们的平行系列“ 使用Yii2编程”

提醒将如何运作

最初,我在UserSetting表中创建了一些简单的提醒选项。 但是,我意识到用户将需要更大的灵活性,并更好地控制提醒的发送时间和方式。

人们应该能够在30分钟之前,3小时之前和48小时之前或仅1小时之前设置提醒。 应该完全取决于他们。 他们还应该能够选择是否要通过电子邮件,短信或两者同时接收提醒。 Meeting Planner尚不支持SMS,但很快就会支持-也将提供有关此主题的教程。

这是Apple Calendar提供的灵活性的示例:

会议计划提醒-Apple日历提醒警报

允许人们设置提醒

让我们构建基础结构以支持任何数量的用户可自定义会议提醒。

会议计划者提醒-创建提醒
提醒表

首先,我创建了一个Reminder表来支持用户针对所有会议的一个或多个提醒请求。 与Yii2一样,我创建了带有迁移的表。

这是Yii控制台命令,用于创建数据库迁移:

./yii migrate/create create_reminder_table

然后,我使用所需的属性自定义了此骨架文件:

class m160503_234630_create_reminder_table extends Migration
{
    public function up()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
        }

        $this->createTable('{{%reminder}}', [
            'id' => Schema::TYPE_PK,
            'user_id' => Schema::TYPE_BIGINT.' NOT NULL',
            'duration_friendly' => Schema::TYPE_INTEGER.' NOT NULL DEFAULT 0',
            'unit' => Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0',
            'duration' => Schema::TYPE_INTEGER.' NOT NULL DEFAULT 0',
            'reminder_type' => Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0',
            'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',
            'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',
        ], $tableOptions);
        $this->addForeignKey('fk_reminder_user', '{{%reminder}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
    }

如果提醒时间是48小时之前,则duration_friendlyunit将为48UNIT_HOURS ,而duration字段将以秒为单位,例如会议前48 * 60分钟* 60秒或172,800秒。 这将有助于简化用户界面和处理提醒。

Reminder_type将指定电子邮件和/或SMS。

然后,我使用Gii(其代码框架生成器)为控制器,模型和视图快速创建MVC代码。 最初的用户界面在几分钟内就准备就绪。 您可以在上方看到创建提醒表单,在下方看到提醒索引。

会议计划者提醒-人员可自定义的提醒
初始化现有和新用户的提醒

到我开始处理提醒时,人们已经在使用Meeting Planner安排会议。 因此,我需要为现有人员以及每个新注册的人员初始化提醒表。

我决定首先应为用户设置三个默认提醒,分别在会议开始前的3小时,1天和3天安排。 下面的代码为用户创建这些提醒:

public static function initialize($user_id) {
      // create initial reminders for a user
      $r1 = new Reminder();
      $r1->user_id = $user_id;
      $r1->duration_friendly = 3;
      $r1->unit = Reminder::UNIT_HOURS;
      $r1->reminder_type = Reminder::TYPE_EMAIL;
      $r1->duration = 3600;
      $r1->validate();
      $r1->save();
      $r2 = new Reminder();
      $r2->user_id = $user_id;
      $r2->duration_friendly = 1;
      $r2->unit = Reminder::UNIT_DAYS;
      $r2->reminder_type = Reminder::TYPE_EMAIL;
      $r2->duration = 1*24*3600;
      $r2->save();
      $r3 = new Reminder();
      $r3->user_id = $user_id;
      $r3->duration_friendly = 3;
      $r3->unit = Reminder::UNIT_DAYS;
      $r3->reminder_type = Reminder::TYPE_EMAIL;
      $r3->duration = $r3->duration_friendly*24*3600;
      $r3->save();
      Reminder::processNewReminder($r1->id);
      Reminder::processNewReminder($r2->id);
      Reminder::processNewReminder($r3->id);
    }

但是processNewReminder做什么? 它在另一个表中构建行,下面将对此进行描述。

处理提醒

很好,我们现在可以为用户提供一种为会议提供默认提醒选项的方法。 但是系统如何知道何时将提醒发送给每个用户的会议? 那更复杂。

出于性能考虑,我认为最好自己构建一个MeetingReminder表。 这将在安排会议时记录用户的默认提醒,并跟踪何时为每个会议发送这些提醒。 基本上,这是一个特定于会议的提醒表,反映了每个参与者配置的提醒首选项。

随着会议时间的更新,该会议的MeetingReminder表条目将需要更改。 同样,如果某人更新了他们的提醒首选项, MeetingReminder表中的预定提醒也将需要刷新。

让我们为MeetingReminder表创建迁移:

./yii migrate/create create_meeting_reminder_table

这是迁移代码; 这很简单。 基本上,对于每个提醒,都有一个MeetingReminder ,它对应于用户的会议提醒。 它知道提醒在某个时间due_at ,并且其状态确定是否已发送:

class m160510_062936_create_meeting_reminder_table extends Migration
{
  public function up()
  {
      $tableOptions = null;
      if ($this->db->driverName === 'mysql') {
          $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
      }

      $this->createTable('{{%meeting_reminder}}', [
          'id' => Schema::TYPE_PK,
          'meeting_id' => Schema::TYPE_INTEGER.' NOT NULL DEFAULT 0',
          'reminder_id' => Schema::TYPE_BIGINT.' NOT NULL',
          'user_id' => Schema::TYPE_BIGINT.' NOT NULL',
          'due_at' => Schema::TYPE_INTEGER . ' NOT NULL',
          'status' => Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0',
      ], $tableOptions);
      $this->addForeignKey('fk_meeting_reminder_user', '{{%meeting_reminder}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
      $this->addForeignKey('fk_meeting_reminder_meeting', '{{%meeting_reminder}}', 'meeting_id', '{{%meeting}}', 'id', 'CASCADE', 'CASCADE');
  }

后台监视作业将能够按到期时间对MeetingReminder表进行排序,并Swift知道实际上需要传递哪些小提醒。 它可以跟踪为每个会议和参与者发送了哪些消息。

注意:目前,没有允许人们自定义特定会议提醒的功能,因此MeetingReminder表没有用户界面。 我可以稍后添加。

正如我之前所暗示的, MeetingReminder表原来造成了许多微妙的复杂性:

  • 如果人们添加,编辑或删除提醒,则必须在预先配置的会议提醒中反映出来。
  • 如果人们更改了会议时间或取消了会议时间,则必须更新会议提醒以反映这一点。
  • 如果某人选择不参加会议,则必须禁用这些提醒。

最终,构建提醒功能需要大量的助手功能。

这是一个帮助程序功能,可为特定用户创建MeetingReminder ,以提醒他们特定的会议。 如果会议已经通过,则状态反映为:

public static function create($meeting_id,$user_id,$reminder_id,$differential) {
  // delete any previously existing meetingreminder for this reminder_id and meeting_id
   MeetingReminder::deleteAll(['meeting_id'=>$meeting_id,'reminder_id'=>$reminder_id]);
   $mtg = Meeting::findOne($meeting_id);
   if (is_null($mtg)) {
     return false;
   }
   $chosen_time = Meeting::getChosenTime($meeting_id);
   $mr = new MeetingReminder;
   $mr->reminder_id = $reminder_id;
   $mr->meeting_id = $meeting_id;
   $mr->user_id = $user_id;
   $mr->due_at = $chosen_time->start-$differential;
   if ($mr->due_at>time()) {
     $mr->status=MeetingReminder::STATUS_PENDING;
   } else {
     $mr->status=MeetingReminder::STATUS_COMPLETE;
   }
   $mr->save();
}

因此,无论何时创建提醒,下面的代码都会为用户的每个会议创建所有MeetingReminder条目:

public static function processNewReminder($reminder_id) {
  $rem = Reminder::findOne($reminder_id);
  // find all the meetings this user is a part of
  // create meeting reminder for all meetings where this reminder's creator is the organizer
  $mtgs = Meeting::find()->where(['owner_id'=>$rem->user_id])->all();
  // to do performance - could add an open join above to participants
  foreach ($mtgs as $m) {
    MeetingReminder::create($m->id,$rem->user_id,$rem->id,$rem->duration);
  }
  // create meeting reminder for all meetings where this reminder's creator is a participant
  $part_mtgs = Participant::find()->where(['participant_id'=>$rem->user_id])->all();
  foreach ($part_mtgs as $m) {
    MeetingReminder::create($m->id,$rem->user_id,$rem->id,$rem->duration);
  }
}

基本上,该代码查找某个人的所有会议(无论是组织者还是参与者),并为该人的每个提醒创建一个MeetingReminder条目。 例如,一个具有三个默认提醒首选项和安排了三个会议的人将有9个MeetingReminder表条目。

处理新提醒

当某人创建一个新的提醒时,我们有一些代码可以根据他们的设置来设置持续时间,然后为其所有待处理的会议创建一个新的MeetingReminder

public function actionCreate()
    {
        $model = new Reminder();
        $model->user_id = Yii::$app->user->getId();
        $model->duration = 0;
        if ($model->load(Yii::$app->request->post())) {
          $model->duration = $model->setDuration($model->duration_friendly,$model->unit);
          if ($model->validate()) {
            $model->save();
            Reminder::processNewReminder($model->id);
            Yii::$app->getSession()->setFlash('success', Yii::t('frontend','Your reminder has been created for all current and future meetings.'));
            return $this->redirect('index');
          } else {
            // to do set flash
            Yii::$app->getSession()->setFlash('error', Yii::t('frontend','There was a problem creating your reminder.'));
          }
        }
        return $this->render('create', [
            'model' => $model,
        ]);
    }

处理提醒更改

如果用户修改请注意,我们需要更新MeetingReminder该表reminder_id

public static function updateReminder($reminder_id) {
      // when user updates a reminder, update all the meeting reminders
      $new_reminder = Reminder::findOne($reminder_id);
      $mrs = MeetingReminder::find()->where(['reminder_id'=>$reminder_id])->all();
      // update each meeting reminder
      foreach ($mrs as $mr) {
        $chosen_time = Meeting::getChosenTime($mr->meeting_id);
        $mr->due_at = $chosen_time->start-$new_reminder->duration;
        if ($mr->due_at>time()) {
          $mr->status=MeetingReminder::STATUS_PENDING;
        } else {
          $mr->status=MeetingReminder::STATUS_COMPLETE;
        }
        $mr->update();
      }
    }

如果提醒的due_at时间已经过去,则我们将其状态设置为完成。

会议结束时的处理

会议结束后,就确定了时间,我们需要根据每个参与者的提醒设置来配置MeetingReminderssetMeetingReminders方法执行以下操作:

public static function setMeetingReminders($meeting_id,$chosen_time=false) {
      // when a meeting is finalized, set reminders for the chosen time for all participants
      $mtg = Meeting::findOne($meeting_id);
      if ($chosen_time ===false) {
        $chosen_time = Meeting::getChosenTime($meeting_id);
      }
      // create attendees list for organizer and participants
      $attendees = array();
      $attendees[0]=$mtg->owner_id;
      $cnt =1;
      foreach ($mtg->participants as $p) {
        if ($p->status ==Participant::STATUS_DEFAULT) {
          $attendees[$cnt]=$p->participant_id;
          $cnt+=1;
        }
      }
      // for each attendee
      foreach ($attendees as $a) {
        // for their reminders
        $rems = Reminder::find()->where(['user_id'=>$a])->all();
        foreach ($rems as $rem) {
          // create a meeting reminder for that reminder at that time
            MeetingReminder::create($meeting_id,$a,$rem->id,$rem->duration);
        }
      }
    }

会议时间变更时的处理

类似地,事实结束后更改会议时间(当前功能集尚不支持)时,我创建了一个简单的功能来删除并重建新时间的MeetingReminders

public static function processTimeChange($meeting_id,$chosen_time) {
      // when a meeting time is set or changes, reset the reminders for all participants
      // clear out old meeting reminders for all users for this meeting
      MeetingReminder::deleteAll(['meeting_id'=>$meeting_id]);
      // set meeting reminders for all users for this meeting
      // note each user has different reminders
      Reminder::setMeetingReminders($meeting_id,$chosen_time);
    }

乍看起来似乎很简单的功能却需要大量的细节和监督。

下一步是什么?

您已经了解了提醒的基础。 在下一个教程中,我将向您展示如何监控时间以了解何时以及如何传递提醒。 我将向您展示我们如何通过电子邮件发送提醒(稍后会发送短信)。

会议计划者提醒-提醒电子邮件示例

等待期间,尝试使用提醒功能, 安排第一次会议 ,然后更新提醒首选项 。 另外,如果您在下面的评论中分享您的经验,我也将不胜感激,并且我始终对您的建议感兴趣。 您也可以直接通过Twitter @reifman与联系

我还将根据SEC新的众筹规则的实施情况,开始对WeFunder进行试验。 请考虑在那里关注我们的个人资料 。 在我们的系列文章中,我可能会写得更多。

在“ 用PHP构建您的启动”系列中观看即将发布的教程。 除了提醒之外,还有很多抛光工作和其他一些重要功能。

相关链接

翻译自: https://code.tutsplus.com/tutorials/building-your-startup-preparing-for-reminders--cms-26527

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值