使用 PHP 构建您的初创公司:安排会议
本教程是Tuts+上“使用PHP构建您的初创公司”系列的一部分。在本系列中,我将使用我的MeetingPlanner应用程序作为现实生活中的示例,指导您启动从概念到现实的初创公司。在此过程中的每一步,我们都会将MeetingPlanner代码作为开源示例发布,您可以从中学习。我们还将解决出现的与初创企业相关的业务问题。MeetingPlanner的所有代码都是用PHP的Yii2框架编写的。如果您想了解有关Yii2的更多信息,请查看Tuts+上的并行系列“使用Yii2编程”。您可能还想查看我的知识库网站,了

本教程是 Tuts+ 上“使用 PHP 构建您的初创公司”系列的一部分。在本系列中,我将使用我的 Meeting Planner 应用程序作为现实生活中的示例,指导您启动从概念到现实的初创公司。在此过程中的每一步,我们都会将 Meeting Planner 代码作为开源示例发布,您可以从中学习。我们还将解决出现的与初创企业相关的业务问题。
Meeting Planner 的所有代码都是用 PHP 的 Yii2 框架编写的。如果您想了解有关 Yii2 的更多信息,请查看 Tuts+ 上的并行系列“使用 Yii2 编程”。您可能还想查看我的知识库网站,了解 Yii2 问题,Yii2 开发者交流中心。
在过去的六个教程中,我们通过多种方式奠定了应用程序支持的基础:用户、地点、联系人、设置和本地化。我打赌您会和我一样兴奋,因为我们终于准备好开始构建安排会议功能了。感谢您的耐心等待,我已经为这个应用程序的有趣且不可或缺的部分构建了基础架构。
但是,支持安排会议功能的编码教程将至少持续四集。接下来的两集将主要关注为基本用户体验建立支持,选择会议的参与者、地点、日期和时间,并将其存储在数据库中。之后,我们将介绍如何通过电子邮件发送会议请求。我们将在本系列稍后返回来优化和完善用户界面,因为它对于该产品的成功至关重要;后续更新的主要任务是消除会议安排过程中的页面刷新。
构建本教程的功能需要大量代码 - 一些由 Yii 的 Gii 自动生成,还有很多是手动生成的。由于交付此功能的初始部分非常复杂,因此我专注于相当基本的用户界面,我将对其进行迭代完善。
构建此功能涉及 Yii2 框架中编程的许多方面:Active Record 迁移、关系和验证、Gii 代码生成、Bootstrap、Yii2 JQuery UI 扩展和小部件、AJAX、渲染部分视图、DRY 编码实践等。很难选择这里要涵盖的内容。您会注意到早期教程中的存储库发生了很多更改。
如果您有任何疑问或意见,请在下面发布。我确实参与了讨论。
会议页面
引导选项卡
我需要做的第一件事就是为未来、过去和取消的会议构建不同的选项卡。

实现这一点只是 Bootstrap 的伟大之处以及 Yii2 与 Bootstrap 3.x 集成的牢固性的另一个例子。 Bootstrap 有预构建的选项卡。
在 MeetingController 中,我们预加载每种会议类型的查询并呈现索引视图:
public function actionIndex()
{
// add filter for upcoming or past
$upcomingProvider = new ActiveDataProvider([
'query' => Meeting::find()->joinWith('participants')->where(['owner_id'=>Yii::$app->user->getId()])->orWhere(['participant_id'=>Yii::$app->user->getId()])->andWhere(['Meeting.status'=>[Meeting::STATUS_PLANNING,Meeting::STATUS_CONFIRMED]]),
]);
$pastProvider = new ActiveDataProvider([
'query' => Meeting::find()->joinWith('participants')->where(['owner_id'=>Yii::$app->user->getId()])->orWhere(['participant_id'=>Yii::$app->user->getId()])->andWhere(['Meeting.status'=>Meeting::STATUS_COMPLETED]),
]);
$canceledProvider = new ActiveDataProvider([
'query' => Meeting::find()->joinWith('participants')->where(['owner_id'=>Yii::$app->user->getId()])->orWhere(['participant_id'=>Yii::$app->user->getId()])->andWhere(['Meeting.status'=>Meeting::STATUS_CANCELED]),
]);
return $this->render('index', [
'upcomingProvider' => $upcomingProvider,
'pastProvider' => $pastProvider,
'canceledProvider' => $canceledProvider,
]);
}
然后,在索引视图中,我们使用选项卡窗格实现引导代码:
= $this->title ?>
随着我们深入了解本系列,我将留下许多占位符工作要做。其中之一是通过 AJAX 实现这些选项卡窗格,这样我们就不会预先加载三个查询。
工单追踪
我还将开始在问题跟踪应用 Lighthouse 中为我未来的工作创建票证,以使其更易于跟踪。我将在以后的教程中讨论 Lighthouse。

安排会议的背后是什么?
创建一个安排会议的框架这个简单的任务在幕后却是相当复杂和详细的。我将在整个系列中分阶段完善这一点。
我的第一个目标是构建基本框架,以便我可以开始测试会议安排的功能。
会议由一些 ActiveRecord 数据模型组成,例如Participant、MeetingTime、MeetingPlace、MeetingNote 等。最初,我只是想使用 Yii 代码生成为每个模型构建 CRUD,然后将其集成到单个调度页面中。
这个想法是使用 MVC 来构建所有这些操作,并尽可能坚持 DRY 方法。最初,该界面将通过页面刷新来工作,但稍后我们将返回并使用相同的 MVC 代码通过 AJAX 集成所有这些模型。
创建会议表单
对于许多模型,我首先经历了早期教程中概述的使用 Yii 代码生成器 Gii 构建 CRUD 的过程。然后我根据需要定制它们。目前,我坚持使用非常基本的创建会议表单 - 它甚至还不包括参与者的电子邮件地址。这使我能够快速创建基本的会议记录并在安排页面上工作。

表单提交后,您可以查看会议页面。显然,我会及时修改这个表格和最初的流程。
会议页面
记住我的本系列第一篇教程的模型:

这是我正在处理的表单的早期版本:

实现这一目标涉及大量基础设施、代码(自动生成、手动生成)和第三方小部件。我将逐步引导您完成它。
引导面板和表格
虽然不太可能是最终设计,但我选择使用 Bootstrap 面板来组织属性、地点、日期、时间和注释之间的页面。页面本身由会议控制器的 View 操作呈现,并调用每个视图的特定模型的部分视图。
我不必以这种方式构建它,但我有目的地想要利用 Yii 的所有内置 MVC 框架并尽可能多地集成事物。我的希望是,将来能够更轻松地对整个页面进行 AJAX 化,减少页面刷新并提高源代码的简单性和可维护性。
以下是会议控制器 View 操作的工作原理。它为每个模型加载 ActiveDataProviders,然后呈现会议视图文件:
/**
* Displays a single Meeting model.
* @param integer $id
* @return mixed
*/
public function actionView($id)
{
$timeProvider = new ActiveDataProvider([
'query' => MeetingTime::find()->where(['meeting_id'=>$id]),
]);
$noteProvider = new ActiveDataProvider([
'query' => MeetingNote::find()->where(['meeting_id'=>$id]),
]);
$placeProvider = new ActiveDataProvider([
'query' => MeetingPlace::find()->where(['meeting_id'=>$id]),
]);
$participantProvider = new ActiveDataProvider([
'query' => Participant::find()->where(['meeting_id'=>$id]),
]);
$model = $this->findModel($id);
$model->prepareView();
return $this->render('view', [
'model' => $model,
'participantProvider' => $participantProvider,
'timeProvider' => $timeProvider,
'noteProvider' => $noteProvider,
'placeProvider' => $placeProvider,
]);
}
部分视图
通过使用每个关联模型中的所有视图,可以非常轻松地使用 MVC 部分视图显示整个计划页面。会议视图呈现其他模型的所有 _panel 视图。您可以在此处查看 Yii2 渲染方法的文档。
= $this->render('../participant/_panel', [
'model'=>$model,
'participantProvider' => $participantProvider,
]) ?>
= $this->render('../meeting-place/_panel', [
'model'=>$model,
'placeProvider' => $placeProvider,
]) ?>
= $this->render('../meeting-time/_panel', [
'model'=>$model,
'timeProvider' => $timeProvider,
]) ?>
= $this->render('../meeting-note/_panel', [
'model'=>$model,
'noteProvider' => $noteProvider,
]) ?>
缺少模型
在构建此功能时,我意识到我忽略了几个必要的模型:MeetingPlaceChoice 和 MeetingTimeChoice。需要这些来存储特定 MeetingPlaces 和 MeetingTimes 的组织者和参与者的可用性。
以下是 MeetingPlaceChoice 的迁移:
$this->createTable('{{%meeting_place_choice}}', [
'id' => Schema::TYPE_PK,
'meeting_place_id' => Schema::TYPE_INTEGER.' NOT NULL',
'user_id' => Schema::TYPE_BIGINT.' NOT NULL',
'status' => 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_mpc_meeting_place', '{{%meeting_place_choice}}', 'meeting_place_id', '{{%meeting_place}}', 'id', 'CASCADE', 'CASCADE');
$this->addForeignKey('fk_mpc_user_id', '{{%meeting_place_choice}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
以下是 MeetingTimeChoice 的迁移:
$this->createTable('{{%meeting_time_choice}}', [
'id' => Schema::TYPE_PK,
'meeting_time_id' => Schema::TYPE_INTEGER.' NOT NULL',
'user_id' => Schema::TYPE_BIGINT.' NOT NULL',
'status' => 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_mtc_meeting_time', '{{%meeting_time_choice}}', 'meeting_time_id', '{{%meeting_time}}', 'id', 'CASCADE', 'CASCADE');
$this->addForeignKey('fk_mtc_user_id', '{{%meeting_time_choice}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
随着产品的进步,Yii 的 ActiveRecord 迁移可以轻松地以编程方式扩展数据库架构。
这些模型确定您在上面的每个地点和日期时间的行中看到的开关小部件的状态(反映用户可用性)。在下面的教程中,我将引导您了解如何初始化这些小部件并在 Yii 中使用 AJAX 来更新它们的状态而无需刷新页面。
安排提醒
PrepareView 确定会议的状态,并在必要时警告用户邀请尚未发送:
public function prepareView() {
$this->setViewer();
$this->canSend();
$this->canFinalize();
// has invitation been sent
if ($this->canSend()) {
Yii::$app->session->setFlash('warning', Yii::t('frontend','This invitation has not yet been sent.'));
}
// to do - if sent, has invitation been opened
// to do - if not finalized, is it within 72 hrs, 48 hrs
}
Yii 具有显示 Bootstrap Alerts 的内置支持,称为 flashes:

命令按钮
以下是示例会议视图容器的代码,其中包含上面所示的命令按钮:
= Html::encode($this->title) ?>
= $model->message ?>
每个按钮都是使用 Yii 的 HTML 帮助器和 Bootstrap 按钮样式创建的:
= Html::a(Yii::t('frontend', 'Send'), ['finalize', 'id' => $model->id], ['class' => 'btn btn-primary '.(!$model->isReadyToSend?'disabled':'')]) ?>
对于取消和编辑属性按钮,我使用了 Glyphicons。 Glyphicons 非常漂亮,并且免费包含在 Bootstrap 中并与 Yii2 集成。
这些命令有什么作用?
用户添加一名参与者以及至少一个地点、日期和时间后,他或她就可以发送邀请。此功能将通过电子邮件向用户发送会议邀请,我将在即将发布的教程中对此进行描述。
最终确定按钮允许组织者(或参与者)将会议状态从计划更改为即将举行。这个想法是,一旦选择了地点和日期时间,会议就可以“最终确定”。在此之前,参与者将有机会选择建议其他地点和日期时间,组织者(或双方)将可以选择最终地点和日期时间。
取消按钮将取消会议并将其移至会议页面上已取消的选项卡。
参与者
接下来,用户将添加人员。

注意:在我的最小可行产品中,只允许一名参与者,但我们稍后可能会添加更多参与者。
em>
如果您还记得我们在之前的教程中创建的“好友”表,我将允许用户输入新的电子邮件地址,或者通过从现有好友和过去的会议中加载自动完成功能来加快输入速度。

将来,我们将在此处提供更多用户界面选项,包括频繁参与者。
在 Participant 控制器的顶部,我们将朋友加载到一个数组中,以供 JQuery 自动完成小部件使用 - Yii2 中再次内置了对此的支持:
/**
* Creates a new Participant model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate($meeting_id)
{
$mtg = new Meeting();
$title = $mtg->getMeetingTitle($meeting_id);
$model = new Participant();
$model->meeting_id= $meeting_id;
$model->invited_by= Yii::$app->user->getId();
// load friends for auto complete field
$friends = Friend::getFriendList(Yii::$app->user->getId());
这是_form.php,位于\frontend\views\participant:
= $form->errorSummary($model); ?>Email address:
$model, 'attribute' => 'email', 'clientOptions' => [ 'source' => $friends, ], ]); ?>我做出了将所有参与者存储在用户表中的设计决策。我可能会后悔——还不确定。但它极大地简化了流程,让人们能够快速开始使用网站,并简化了整体数据模型。
当用户邀请系统未知的人(新电子邮件地址)时,我们会在用户表中被动注册他们。
if ($model->load(Yii::$app->request->post())) { if (!User::find()->where( [ 'email' => $model->email ] )->exists()) { // if email not already registered // create new user with temporary username & password $temp_email_arr[] = $model->email; $model->username = Inflector::slug(implode('-', $temp_email_arr)); $model->password = Yii::$app->security->generateRandomString(12); $model->participant_id = $model->addUser(); } else { // add participant from user record $usr = User::find()->where( [ 'email' => $model->email ] )->one(); $model->participant_id = $usr->id; } // validate the form against model rules if ($model->validate()) { // all inputs are valid $model->save(); return $this->redirect(['/meeting/view', 'id' => $meeting_id]); }我们根据他们的电子邮件地址创建用户名。我在 Inflector 助手中使用 Yii 的 slug 生成器。我们现在使用 Yii 的安全助手创建一个随机密码。如果我使用普通 PHP,我可能必须集成其他函数才能实现这些功能。相反,它是内置的。
让我们继续添加地点。
地点
对每个控制器和模型使用 Yii 的 MVC 比将所有这些功能编码到会议控制器中具有很大的优势。它使理解和管理代码变得更加简单和更有条理。
但是,我很快注意到,我必须自定义默认面包屑以链接回当前会议页面,而不是特定模型的索引或视图。
我们实际上使用
MeetingPlace模型来添加会议地点。在\frontend\views\meeting-place\create.php中,我只需自定义breadcrumbs区域中的链接:title = Yii::t('frontend', 'Add a {modelClass}', [ 'modelClass' => 'Meeting Place', ]); $this->params['breadcrumbs'][] = ['label' => Yii::t('frontend', 'Meetings'), 'url' => ['/meeting/index']]; $this->params['breadcrumbs'][] = ['label'=>$title,'url' => ['/meeting/view', 'id' => $model->meeting_id]]; $this->params['breadcrumbs'][] = $this->title; ?>添加对直接添加 Google 地点的支持
我不仅想自定义地点创建表单,以便用户添加以前使用过的地点,还希望他们添加新的 Google 地方信息正在运行。
我基本上必须在
MeetingPlace创建中复制我们在 Google 地方信息教程中构建的支持:= $form->errorSummary($model); ?>Choose one of your places
= 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'); ?>= Html::activeDropDownList($model, 'place_id', ArrayHelper::map(UserPlace::find()->all(), 'place.id', 'place.name'),['prompt'=>Yii::t('frontend','-- select one of your places below --')] ) ?>- or -
Choose from Google Places
Type in a place or business known to Google Places:
= $form->field($model, 'searchbox')->textInput(['maxlength' => 255])->label('Place') ?>= Html::submitButton($model->isNewRecord ? Yii::t('frontend', 'Add Place') : Yii::t('frontend', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>我还需要更多地利用 Yii2 复杂的验证支持。在下面的
MeetingPlace模型中,如果有人尝试前往已建议的会议地点,我们会使用 Yii2 的独特验证来报告错误:public function rules() { return [ [['meeting_id', 'place_id', 'suggested_by'], 'required'], [['meeting_id', 'place_id', 'suggested_by', 'status', 'created_at', 'updated_at'], 'integer'], [['place_id'], 'unique', 'targetAttribute' => ['place_id','meeting_id'], 'message'=>Yii::t('frontend','This place has already been suggested.')],我还在
MeetingPlaceController创建操作中添加了一个自定义错误条件(如果用户从其列表以及 Google Place 中选择地点),尽管这可能是一个需要保留的可选功能(有意见吗?请在下面的评论中发表):public function actionCreate($meeting_id) { $mtg = new Meeting(); $title = $mtg->getMeetingTitle($meeting_id); $model = new MeetingPlace(); $model->meeting_id= $meeting_id; $model->suggested_by= Yii::$app->user->getId(); $model->status = MeetingPlace::STATUS_SUGGESTED; $posted_form = Yii::$app->request->post(); if ($model->load($posted_form)) { // check if both are chosen and return an error if ($model->place_id<>'' and $posted_form['MeetingPlace']['google_place_id']<>'') { $model->addErrors(['place_id'=>Yii::t('frontend','Please choose one or the other')]); return $this->render('create', [ 'model' => $model, 'title' => $title, ]); }我使用了 Yii2 的 addErrors 方法。
我还修复了第三集中的一个错误,即每当有人更改 Google 地点选择时就会创建多个地图框。检查
article选择器中现有的子级数量修复了此问题:function loadMap(gps,name) { 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 solid black'; document.querySelector('article').appendChild(mapcanvas); }未来,这种创作形式将包含一些重要的功能:
- 允许用户添加他们当前的地理位置。
- 推荐用户推荐的常去地点。
- 提供对用户最喜爱的地点的快速访问。
- 建议用户和参与者附近(等距离)的地点。
- 建议付费广告商赞助的地点。
- 允许组织者删除地点和日期时间 - 可能是在参与者未看到或回复的情况下。
允许用户记录特定地点和日期时间也可能很有用。例如,我可能会指定“这个地方适合我周四早上但周五下午不适合”或“如果您选择这个时间,我们可以在国会山的 Caffe Vita 进行吗”。如果您对此功能有意见(这会增加复杂性),请在下面发表评论。
显示面板
对于每个模型,我们使用类似的视图层次结构和 Yii2 组件。会议控制器在
\frontend\views\meeting-place中呈现_panel.php的视图:count>0): ?>= Yii::t('frontend','Places') ?>
= Html::a('', ['meeting-place/create', 'meeting_id' => $model->id], ['class' => 'btn btn-primary glyphicon glyphicon-plus']) ?>
= ListView::widget([ 'dataProvider' => $placeProvider, 'itemOptions' => ['class' => 'item'], 'layout' => '{items}', 'itemView' => '_list', 'viewParams' => ['placeCount'=>$placeProvider->count], ]) ?> =Yii::t('frontend','You') ?> =Yii::t('frontend','Them') ?> count>1) echo Yii::t('frontend','Choose'); ?> Bootstrap 兼容表的概要位于
_panel.php中。然后我们使用 Yii2 Listview 小部件以表格形式显示每一行数据。itemView部分位于_list.php中。请注意,我们通过
viewParams传递了一个名为placeCount的自定义变量。这对于配置表格中的按钮非常方便。这是
_list.php视图,我将在下一个教程中更详细地介绍该视图,包括切换输入小部件和 AJAX 实现。= Html::a($model->place->name,BaseUrl::home().'/place/'.$model->place->slug) ?> foreach ($model->meetingPlaceChoices as $mpc) { if ($mpc->user_id == $model->meeting->owner_id) { if ($mpc->status == $mpc::STATUS_YES) $value = 1; else $value =0; echo SwitchInput::widget([ 'type'=>SwitchInput::CHECKBOX, 'name' => 'meeting-place-choice', 'id'=>'mpc-'.$mpc->id, 'value' => $value, 'pluginOptions' => ['size' => 'mini','onText' => '','offText'=>'','onColor' => 'success','offColor' => 'danger',], ]); } } ?> foreach ($model->meetingPlaceChoices as $mpc) { if (count($model->meeting->participants)==0) break; if ($mpc->user_id == $model->meeting->participants[0]->participant_id) { if ($mpc->status == $mpc::STATUS_YES) $value = 1; else if ($mpc->status == $mpc::STATUS_NO) $value =0; else if ($mpc->status == $mpc::STATUS_UNKNOWN) $value =-1; echo SwitchInput::widget([ 'type'=>SwitchInput::CHECKBOX, 'name' => 'meeting-place-choice', 'id'=>'mpc-'.$mpc->id, 'tristate'=>true, 'indeterminateValue'=>-1, 'indeterminateToggle'=>false, 'disabled'=>true, 'value' => $value, 'pluginOptions' => ['size' => 'mini','onText' => '','offText'=>'','onColor' => 'success','offColor' => 'danger'], ]); } } ?> if ($placeCount>1) { if ($model->status == $model::STATUS_SELECTED) { $value = $model->id; } else { $value = 0; } echo SwitchInput::widget([ 'type' => SwitchInput::RADIO, 'name' => 'place-chooser', 'items' => [ [ 'value' => $model->id], ], 'value' => $value, 'pluginOptions' => [ 'size' => 'mini','handleWidth'=>60,'onText' => '','offText'=>''], 'labelOptions' => ['style' => 'font-size: 12px'], ]); } ?> 日期和时间
为了添加日期和时间,我们通过 2Amigos Yii2 日期时间扩展集成了 Bootstrap JQuery 日期时间选择器
本文内容来源于互联网,如有侵权请联系删除。= DateTimePicker::widget([ 'model' => $model, 'attribute' => 'start', 'language' => 'en', 'size' => 'ms', 'clientOptions' => [ 'autoclose' => true, 'format' => 'MM dd, yyyy HH:ii P', 'todayBtn' => true, 'minuteStep'=> 15, 'pickerPosition' => 'bottom-left', ] ]);?>= Html::submitButton($model->isNewRecord ? Yii::t('frontend', 'Add') : Yii::t('frontend', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>我希望将来对这个小部件进行一些增强。我想让它在加载时自动打开,但目前似乎没有相应的设置。
我们再次使用唯一的验证器来确保特定日期和时间尚未添加到会议中:
public function rules() { return [ [['meeting_id', 'start', 'suggested_by'], 'required'], [['meeting_id', 'start', 'suggested_by', 'status', 'created_at', 'updated_at'], 'integer'], [['start'], 'unique', 'targetAttribute' => ['start','meeting_id'], 'message'=>Yii::t('frontend','This date and time has already been suggested.')], ]; }在会议视图页面上,“日期和时间”面板的构建方式与“地点”类似:
count>0): ?>= Yii::t('frontend','Dates & Times') ?>
= Html::a(Yii::t('frontend', ''), ['meeting-time/create', 'meeting_id' => $model->id], ['class' => 'btn btn-primary glyphicon glyphicon-plus']) ?>
= ListView::widget([ 'dataProvider' => $timeProvider, 'itemOptions' => ['class' => 'item'], 'layout' => '{items}', 'itemView' => '_list', 'viewParams' => ['timeCount'=>$timeProvider->count], ]) ?> =Yii::t('frontend','You') ?> =Yii::t('frontend','Them') ?> count>1) echo Yii::t('frontend','Choose'); ?> 这是
_list.php视图:= Meeting::friendlyDateFromTimestamp($model->start) ?> foreach ($model->meetingTimeChoices as $mtc) { if ($mtc->user_id == $model->meeting->owner_id) { if ($mtc->status == $mtc::STATUS_YES) $value = 1; else $value =0; echo SwitchInput::widget([ 'type' => SwitchInput::CHECKBOX, 'name' => 'meeting-time-choice', 'id'=>'mtc-'.$mtc->id, 'value' => $value, 'pluginOptions' => ['size' => 'mini','onText' => '','offText'=>'','onColor' => 'success','offColor' => 'danger',], ]); } } ?> foreach ($model->meetingTimeChoices as $mtc) { if (count($model->meeting->participants)==0) break; if ($mtc->user_id == $model->meeting->participants[0]->participant_id) { if ($mtc->status == $mtc::STATUS_YES) $value = 1; else if ($mtc->status == $mtc::STATUS_NO) $value =0; else if ($mtc->status == $mtc::STATUS_UNKNOWN) $value =-1; echo SwitchInput::widget([ 'type' => SwitchInput::CHECKBOX, 'name' => 'meeting-time-choice', 'id'=>'mtc-'.$mtc->id, 'tristate'=>true, 'indeterminateValue'=>-1, 'indeterminateToggle'=>false, 'disabled'=>true, 'value' => $value, 'pluginOptions' => ['size' => 'mini','onText' => '','offText'=>'','onColor' => 'success','offColor' => 'danger',], ]); } } ?> if ($timeCount>1) { if ($model->status == $model::STATUS_SELECTED) { $value = $model->id; } else { $value = 0; } echo SwitchInput::widget([ 'type' => SwitchInput::RADIO, 'name' => 'time-chooser', 'items' => [ [ 'value' => $model->id], ], 'value' => $value, 'pluginOptions' => [ 'size' => 'mini','handleWidth'=>60,'onText' => '','offText'=>''], 'labelOptions' => ['style' => 'font-size: 12px'], ]); } ?> 注释
会议笔记允许用户根据他们的建议来回沟通并选择地点和日期时间,而无需实际分别向彼此发送电子邮件。
会议页面上的注释如下所示:
注释的实现与上述地点和日期时间的实现几乎相同。您可以查看
MeetingNote控制器和\frontend\views\meeting-note视图文件以获取更多信息。下一步是什么?
我希望您通过本教程学到了一些新东西。请观看我的“使用 PHP 构建您的初创公司”系列中即将推出的教程 - 即将推出许多有趣的功能。
在下一个教程中,我将深入探讨如何使用 AJAX 实现地点和日期时间选择。之后,我们将开始构建电子邮件以发送消息邀请、在日程安排页面上收集参与者的回复,并最终确定现实世界的会议。
请随时在下面添加您的问题和评论;我一般都会参与讨论。您还可以通过 Twitter @reifman 联系我或直接给我发送电子邮件。
相关链接
- 使用 Yii2 编程:入门
- Yii 开发者交流中心
作者最新文章索尼 Xperia 1 VIII / VII / VI 等手机获 Android 17 更新,新增桌面模式等功能 2026-09-08 16:44加拿大留学监护声明书(IMM 5646)双页签署与公证核对指南 2026-09-03 15:02在线PDF转图片教程:一键生成高清图片包 2026-09-03 12:04Creo零基础入门:新建零件与第一次拉伸建模完整指南 2026-09-03 06:02扫描件PDF转Word的在线操作步骤与编辑可行性判断 2026-09-02 18:39热门文章 更多精品专题 更多Mac软件 更多WINDOWS 更多
Windows 10WindowsWindows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式Windows/macOS/Linux极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。























