() translation by (you can also view the original English article)



Ang tutorial na ito ay bahagi ngserye tungkol sa pagbuo ng iyong startup gamit ang PHP sa Envato Tuts+. Sa seryeng ito, gagabayan ko kayo sa paglulunsad ng isang startup mula sa konsepto sa kasalukuyan gamit ang aking Meeting Planner app bilang isang makatotohanan na halimbawa. Bawat hakbang sa kahabaan ng proseso, ibibigay ko ang open-source code ng aking Meeting Planner app bilang halimbawa kung saan maaari mong malaman ang pinagmulan. Tatalakayin ko din angmga isyu tungkol sa negosyo kung meron tayong madaanan.
Panimula sa pulong ng mga grupo
Pagiiskedyul ng pulong kasama ang mga maraming kalahok ay palaging parte na ng aking plano – ngunit hindi parte ng naunang Minimum Viable Product (MVP). Ang unang pagpapalabas ng taga-plano ng pulong na inilunsad nang mayroon lamang 1:1 na pag iskedyul. Ang layunin ng pag suporta sa pag-iskedyul ng grupo ay gaya ng isang listahan ng isang umaakyat sa bundok Everest na hangad marating ang pitong tuktok (at ako namaý hindi umaakyat sa labas).
Ang maraming kalahok sa pulong ay ang pinaka mahirap na gawan ng iskedyul kung kaya’t mahalaga para sa tagaplano ng pulong ang mga produkto na maiaalok. Akoý natutuwa nang ang beta task list ay narating ang punto kung saan akoý maari nang magsimula.
Ako ay nagpaplano, architecting at coding nang pulong ng grupo sa aking isipan nung halos simula pa lamang. Umaasa ako na ang pagbabago sa site para sa tampok na ito ay hindi nangangailangan ng makahulugang UX na pagbabago o coding updates. Ito palaý nangangailangan ng taga-ugnay, 7-10 araw na nakatuon sa trabaho at pagsubok ngunit wala namang malakihang re-architecting.
Sa katunayan, ang pagsubok ay nagpapatunay na ito ang pinakamahirap na aspeto ng pagbuo ng tampok na ito. Ito rin ay nakatulong sa paghahayag ng mga pagkukulang sa mga naunang mga code. Itoý hindi ganun kadali….pagpapadala sa maramihang email addresses, pagtingin na dapat lahat sila ay nakatanggap ng tamang abiso at hindi ang maling abiso — at Makita ang lahat ng tamang talaan ng mga pagpipilian sa kabuuan ng site.
Sa pagtuturo ngayon, aking sasakupin kung paano mag- enable ng maramihang kalahok, pag-upgrade ng UX para sa grupo, paghirang sa mga bumubuo, pagtanggal sa mga kalahok, at paghihiwalay ng pagpipilian ng sa petsa, oras at lugar sa pamamagitan ng kung ano ang mas alam ng mga kalahok.
Sa susunod na pagtuturo, aking ilalarawan ang iba pang gagawin: pag-aralan ang lahat ng lugar nang site na maapektuhan ng maraming kalahok sa mga pulong, ang paggawa at maayos na pag display ng listahan ng mga tatanggap ng mga ibat ibang katayuan, tamang pangangasiwa ng mga abiso, at pag-sala ng mga abiso para sa grupo, at sa huli ay ang pag -upgrade ng kamakailan lamang na inilunsad na kahilingan na tampok na pagbabago sa pulong.
Subukang mag-iskedyul ng pulong ng mga grupo
Kung maari sana ay mag iskedyul ng pulong ng mga grupo ngayon! Ibahagi ang inyong mga saloobin at katugunan sa mga komento sa ilalim.
Sumasali talaga ako sa mga diskusyon ng mga komento sa ibaba, ngunit Maaari mo din akong makausap nang direkta sa Twitter @reifman. Bukas ang aking isipan sa mga bagong
ideya para sa taga-plano ng pulong pati na rin ang mga mungkahi para sa
panghinaharap pang mga serye.
Bilang paalala, ang lahat ng mga code para sa Meeting Planner ay nakasulat sa Yii2 Framework para sa PHP. Kung gusto mong matuto nang iba pa tungkol sa Yii2, tingnan ang aming parallel series Programming Sa Yii2. Kung gusto mong matuto nang iba pa tungkol sa Yii2, tingnan ang aming parallel series Programming Sa Yii2. Marami akong narinig na magagandang bagay tungkol sa Laravel, ngunit ang Yii2 sa kadalasan ay nakakamit ang aking mga pangangailangan ng mas mabilis at walang hirap.
Pagbabalik-tanaw
Noong una kong dinisenyo ang Meeting Planner scheduling interface, ipinakikita nito ang kung anong mayroon sa kasalukuyan ang isang kalahok na makikita sa sarili nitong hanay. At ito ay medyo nakakalito dahil mayroon mga disabled controls.



SA mga oras na iyon, Nag-aalala ako kung paano ko gagawan ng espasyo para maipakita ang availability ng grupo.
Sa kabutihang-palad, Nang aking binuo ulit ang UX para sa mas mabuting karanasan, Pinalitan ko ang participant availability column nang maigsing text summary:



Ang text summary of availability ay nagkataon namang aayon sa pulong ng mga grupo.
Sa muling pagdidisenyo ng mobile first, Nalutas ko ang pinaka importanteng UX barrier sa maramihang kalahok sa pulong!
Coding para sa pulong ng mga grupo
Ating simulan sa pamamagitan ng pagtingin sa lahat ng codes at subukan na ang maramihang kalahok sa pulong ay kinakailangan.
Enabling Multiple Participants



Ang nakakatuwang aspeto sa pulong ng mga grupo ay ang paganahin sila nang diretsuhan. Kailangan ko lang isara ang disabling ng plus icon button sa Who panel para sa pulong sa yugto ng pagpaplano:
1 |
<div class="col-lg-2 col-md-2 col-xs-2"> |
2 |
<div style="float:right;"> |
3 |
<?= Html::a(Yii::t('frontend', ''), ['/participant/create', 'meeting_id' => $model->id], ['class' => 'btn btn-primary '.($model->status>=$model::STATUS_CONFIRMED?'disabled':'').' glyphicon glyphicon-plus']) ?> |
4 |
</div>
|
5 |
</div>
|
Pagkatapos, sinumulan ko sa paglikha ng
MEETING_LIMIT
sa Participant model:
1 |
class Participant extends \yii\db\ActiveRecord |
2 |
{
|
3 |
...
|
4 |
|
5 |
const MEETING_LIMIT = 15; |
Ito’y ginamit sa ParticipantController::actionCreate()
na pagsumite:
1 |
public function actionCreate($meeting_id) |
2 |
{
|
3 |
if (!Participant::withinLimit($meeting_id)) { |
4 |
Yii::$app->getSession()->setFlash('error', Yii::t('frontend','Sorry, you have reached the maximum number of participants per meeting. Contact support if you need additional help or want to offer feedback.')); |
5 |
return $this->redirect(['/meeting/view', 'id' => $meeting_id]); |
6 |
}
|
Pagsulong sa UX at iba pang kahalintulad na tampok
Sa matagal na panahon, Gusto kong payagan ang mga taga-organiza ng pulong na magtanggal ng mga kalahok, mga lugar at petsa nang hindi nagugulo ang user interface. Katulad nito, napagtanto ko na maaring may mga ilang commands na maaring gawin sa mga kalahok.
Pagkatapos makahanap ng maraming utility sa compact Bootstrap dropdown button sa Advanced Commands tutorial, nagdesisyon akong gamitin ito para idisplay ang dadalo sa pulong:



Ang mga taga-organiza ay minarkahan ng bituin. Ang mga dadalo na tumanggi sa pulong ay nakamarka ng orange. Ang mga dadalo na tinanggal ng mga organizers ay nakamarka ng red.
Narito ang mga code sa aking bagong partial /frontend/views/participant/_buttons.php:
1 |
<div class="btn-group btn-participant"> |
2 |
<button type="button" class="btn btn-default btn-sm dropdown-toggle " data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
3 |
<span class="glyphicon glyphicon-star red-star aria-hidden="true"></span> |
4 |
<?= MiscHelpers::getDisplayName($model->owner_id) ?> |
5 |
<span class="caret"></span> |
6 |
</button>
|
7 |
<ul class="dropdown-menu"> |
8 |
<li><?= Html::a(Yii::t('frontend','Send a message'),Url::to('mailto:'.$model->owner->email))?></li> |
9 |
</ul>
|
10 |
</div>
|
Sino man ay maaring magpadala ng mensahe sa kahit na sinong kalahok (ang mga tampok na tala ay kasalukuyang nakapamahagi sa lahat ng kalahok sa pulong).
Ang mga taga-organiza ay nakakakita ng mas malalim na dropdown kung saan pinahihintulutan silang makapagdagdag ng taga-organiza, i.e. Make organizer. Ito ngayon ay isa nang magandang katangian Ang mga taga-organiza ay makakatanggap ng mas kumpletong abiso at mas may kapanyarihan sa lahat ng parte ng pagpapalano. Maaari din nila alisin mga kalahok.
Pagbuo ng AJAX Features para sa Participant Buttons
Nagdesisyon ako para ma-AJAXify ang lahat ng talaan ng pagpipilian. Na nangangailangan pala ng madaming oras nang pag-coding.
Narito ang mga code na tumutukoy sa mga initial button menu at maihanda ang JavaScript:
1 |
<?php
|
2 |
if (count($model->participants)>0) { |
3 |
foreach ($model->participants as $p) { |
4 |
if ($p->participant->id==Yii::$app->user->getId()) { |
5 |
continue; |
6 |
}
|
7 |
$btn_color = 'btn-default'; |
8 |
if ($p->status == Participant::STATUS_DECLINED) { |
9 |
$btn_color = 'btn-warning'; |
10 |
} else if ($p->status == Participant::STATUS_REMOVED || $p->status == Participant::STATUS_DECLINED_REMOVED) { |
11 |
$btn_color = 'btn-danger'; |
12 |
}
|
13 |
?>
|
14 |
<div class="btn-group btn-participant"> |
15 |
<button id="btn_<?= $p->id ?>" type="button" class="btn <?= $btn_color ?> btn-sm dropdown-toggle " data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
16 |
<span id="star_<?= $p->id ?>" class="glyphicon glyphicon-star red-star <?= (!$p->isOrganizer())?'hidden':''?>" aria-hidden="true"></span> |
17 |
<?= MiscHelpers::getDisplayName($p->participant->id) ?> |
18 |
<span class="caret"></span> |
19 |
</button>
|
20 |
<ul class="dropdown-menu"> |
21 |
<li><?= Html::a(Yii::t('frontend','Send a message'),Url::to('mailto:'.$p->participant->email))?></li> |
22 |
<?php if ($model->isOrganizer()) { |
23 |
?>
|
24 |
<li role="separator" class="divider"></li> |
25 |
<li id="mo_<?= $p->id ?>" class="<?= ($p->isOrganizer())?'hidden':''?>"><?= Html::a(Yii::t('frontend','Make organizer'),'javascript:void(0);',['onclick' => "toggleOrganizer($p->id,true);return false;"]); ?></li> |
26 |
<li id="ro_<?= $p->id ?>" class="<?= (!$p->isOrganizer())?'hidden':''?>"><?= Html::a(Yii::t('frontend','Revoke organizer role'),'javascript:void(0);',['onclick' => "toggleOrganizer($p->id,false);return false;"]); ?></li> |
27 |
<li id="rp_<?= $p->id ?>" class="<?= ($p->status == Participant::STATUS_REMOVED || $p->status == Participant::STATUS_DECLINED_REMOVED)?'hidden':''?>"><?= Html::a(Yii::t('frontend','Remove participant'),'javascript:void(0);',['onclick' => "toggleParticipant($p->id,false,$p->status);return false;"]); ?></li> |
28 |
<li id="rstp_<?= $p->id ?>" class="<?= ($p->status != Participant::STATUS_REMOVED && $p->status != Participant::STATUS_DECLINED_REMOVED)?'hidden':''?>"><?= Html::a(Yii::t('frontend','Restore participant'),'javascript:void(0);',['onclick' => "toggleParticipant($p->id,true,$p->status);return false;"]); ?></li> |
29 |
<?php
|
30 |
}
|
31 |
?>
|
32 |
</ul>
|
33 |
</div>
|
Napakaraming button states, kulay at
bituin para i-update dahil ang pagbabago ay ginawa interactively sa pahina kung
saan ang mga code ay nagiging masikot. Dinagdagan ko ng functions sa meeting.js
Javascript file para sa toggleOrganizer( )
, i.e. make/unset organizer, at
toggleParticipant( )
, i.e. remove/restore participant as attendee.
1 |
function toggleOrganizer(id, val) { |
2 |
if (val === true) { |
3 |
arg2 = 1; |
4 |
} else { |
5 |
arg2 =0; |
6 |
}
|
7 |
$.ajax({ |
8 |
url: $('#url_prefix').val()+'/participant/toggleorganizer', |
9 |
data: {id: id, val: arg2}, |
10 |
success: function(data) { |
11 |
if (data) { |
12 |
if (val===false) { |
13 |
$('#star_'+id).addClass("hidden"); |
14 |
$('#ro_'+id).addClass("hidden"); |
15 |
$('#mo_'+id).removeClass("hidden"); |
16 |
} else { |
17 |
$('#star_'+id).removeClass("hidden"); |
18 |
$('#ro_'+id).removeClass("hidden"); |
19 |
$('#mo_'+id).addClass("hidden"); |
20 |
}
|
21 |
}
|
22 |
return true; |
23 |
}
|
24 |
});
|
25 |
}
|
26 |
|
27 |
function toggleParticipant(id, val, original_status) { |
28 |
if (val === true) { |
29 |
arg2 = 1; |
30 |
} else { |
31 |
arg2 =0; |
32 |
}
|
33 |
$.ajax({ |
34 |
url: $('#url_prefix').val()+'/participant/toggleparticipant', |
35 |
data: {id: id, val: arg2, original_status: original_status}, |
36 |
success: function(data) { |
37 |
if (data) { |
38 |
if (val===false) { |
39 |
$('#rp_'+id).addClass("hidden"); |
40 |
$('#rstp_'+id).removeClass("hidden"); |
41 |
$('#btn_'+id).addClass("btn-danger"); |
42 |
$('#btn_'+id).removeClass("btn-default"); |
43 |
} else { |
44 |
$('#rp_'+id).removeClass("hidden"); |
45 |
$('#rstp_'+id).addClass("hidden"); |
46 |
if (original_status==100) { |
47 |
$('#btn_'+id).addClass("btn-warning"); |
48 |
$('#btn_'+id).removeClass("btn-danger"); |
49 |
} else { |
50 |
$('#btn_'+id).addClass("btn-default"); |
51 |
$('#btn_'+id).removeClass("btn-danger"); |
52 |
}
|
53 |
}
|
54 |
}
|
55 |
return true; |
56 |
}
|
57 |
});
|
58 |
}
|
Ang mga ito ay kailangan sabayan ng JSON controller methods sa ParticipantController,php upang ma proseso ang toggle requests at update ng databases:
1 |
public function actionToggleorganizer($id,$val) { |
2 |
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; |
3 |
// change setting
|
4 |
$p=Participant::findOne($id); |
5 |
if ($p->meeting->isOrganizer()) { |
6 |
$p->email = $p->participant->email; |
7 |
if ($val==1) { |
8 |
$p->participant_type=Participant::TYPE_ORGANIZER; |
9 |
} else { |
10 |
$p->participant_type=Participant::TYPE_DEFAULT; |
11 |
}
|
12 |
$p->update(); |
13 |
return true; |
14 |
} else { |
15 |
return false; |
16 |
}
|
17 |
|
18 |
}
|
19 |
|
20 |
public function actionToggleparticipant($id,$val) { |
21 |
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; |
22 |
// change setting
|
23 |
$p=Participant::findOne($id); |
24 |
if ($p->meeting->isOrganizer()) { |
25 |
$p->email = $p->participant->email; |
26 |
if ($val==0) { |
27 |
if ($p->status == Participant::STATUS_DECLINED) { |
28 |
$p->status=Participant::STATUS_DECLINED_REMOVED; |
29 |
} else { |
30 |
$p->status=Participant::STATUS_REMOVED; |
31 |
}
|
32 |
} else { |
33 |
if ($p->status == Participant::STATUS_DECLINED_REMOVED) { |
34 |
$p->status=Participant::STATUS_DECLINED; |
35 |
} else { |
36 |
$p->status=Participant::STATUS_DEFAULT; |
37 |
}
|
38 |
}
|
39 |
$p->update(); |
40 |
return true; |
41 |
} else { |
42 |
return false; |
43 |
}
|
44 |
}
|
Pag-Activate sa Accordion Feature on Panels



Sa oras na ito, napagtanto ko na habang ang plano sa pulong ay mas nagiging kumplikado kasabay nang mas marami pang tatanggap at pagpipilian, magkakaroon ng mas higit pang pag-scrolling. Nagdesisyon akong ipatupad ang Bootstrap accordion feature para sa lahat ng panels sa ating meeting view.
Sa madaling salita, maari mo nang i-click sa heading upang maisara o mabuksan ang bawat isa o ang lahat ng mga panels.
Narito ang mga pagbabago para sa partials ng meeting place _panel.php:
1 |
<div class="panel panel-default"> |
2 |
<!-- Default panel contents -->
|
3 |
<div class="panel-heading" role="tab" id="headingWhere"> |
4 |
<div class="row"> |
5 |
<div class="col-lg-10 col-md-10 col-xs-10" ><h4 class="meeting-place"> |
6 |
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseWhere" aria-expanded="true" aria-controls="collapseWhere"><?= Yii::t('frontend','Where') ?></a> |
7 |
</h4><p>
|
8 |
<div class="hint-text heading-pad"> |
9 |
<?php if ($placeProvider->count<=1) { ?> |
10 |
<?= Yii::t('frontend','add places for participants or switch to \'virtual\'') ?> |
11 |
<?php } elseif ($placeProvider->count>1) { ?> |
12 |
<?= Yii::t('frontend','are listed places okay? ') ?> |
13 |
<?php
|
14 |
}
|
15 |
?>
|
16 |
... |
17 |
<div id="collapseWhere" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingWhere"> |
18 |
<div class="panel-body"> |
19 |
<?php
|
20 |
$style = ($model->switchVirtual==$model::SWITCH_VIRTUAL?'none':'block'); |
21 |
?>
|
22 |
<div id ="meeting-place-list" style="display:<?php echo $style; ?>"> |
23 |
<?php
|
24 |
if ($placeProvider->count>0): |
25 |
?>
|
26 |
<table class="table"> |
27 |
<?= ListView::widget([ |
28 |
'dataProvider' => $placeProvider, |
29 |
'itemOptions' => ['class' => 'item'], |
30 |
'layout' => '{items}', |
31 |
'itemView' => '_list', |
32 |
'viewParams' => ['placeCount'=>$placeProvider->count,'isOwner'=>$isOwner,'participant_choose_place'=>$model->meetingSettings['participant_choose_place'],'whereStatus'=>$whereStatus], |
33 |
]) ?> |
34 |
</table>
|
35 |
Tandaan, ang settings sa itaas ng
panel-heading
at pagkatapos ay ang nakapaligid na div para sa panel-body
. Ang
mga ito ay nag kokontrol ng pagbukas at pagsara ng bawat panel.
Itoý naghatid ng ilang maliliit na problema sa itsura gaya nang unwanted padding na nakapalibot sa listahan ng mga bagay, kung saan ay kailangan ko itong ayusin sa darating na panahon.
Model Infrastructure para sa pulong ng mga grupo
Habang akoý nagpaplano para sa maramihang kalahok na halos mula pa sa umpisa, mayroon mga maliliit hanggang sa katamtamang imprastrakturang pinahusay upang suportahan ang mga ito.
Habang ang MeetingTimeChoice
at
MeetingPlaceChoice
models ay na-aantabayanan kung ang mga kalahok ay may
gustong partikular na araw, oras at mga lugar, Gusto kong antabayanan ang
kabuuan kung saan ay pwede ang lahat ng
kalahok sa bawat araw, oras at lugar. Akoý mapahihintulutan nitong mai-bukod
ang lugar at oras ayon sa kung gaano sila ka-sikat – at maipapakita ang
pinaka-sikat na settings sa pinaka-tuktok ng panels.
Una, lumikha ako ng migration upang mkapagdagdag sa parehong modelo. Madalang na ang naggawa kong migration ay nakaka-apekto sa maramihang mga modelo, kung kaya’t ang isang ito ay espesyal:
1 |
<?php
|
2 |
|
3 |
use yii\db\Schema; |
4 |
use yii\db\Migration; |
5 |
|
6 |
class m160824_235517_extend_meeting_place_and_time extends Migration |
7 |
{
|
8 |
public function up() |
9 |
{
|
10 |
$tableOptions = null; |
11 |
if ($this->db->driverName === 'mysql') { |
12 |
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; |
13 |
}
|
14 |
$this->addColumn('{{%meeting_time}}','availability',Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0'); |
15 |
$this->addColumn('{{%meeting_place}}','availability',Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0'); |
16 |
}
|
17 |
|
18 |
public function down() |
19 |
{
|
20 |
$this->dropColumn('{{%meeting_time}}','availability'); |
21 |
$this->dropColumn('{{%meeting_place}}','availability'); |
22 |
}
|
23 |
}
|
Sa kapasidad nito, naggawa kong simulang
idisplay ang mga posibleng araw, oras at lugar ng pulong na kung saan ay
magkakabukod ayon sa kanilang kasikatan sa mga kalahok, mula MeetingController::actionView()
:
1 |
$timeProvider = new ActiveDataProvider([ |
2 |
'query' => MeetingTime::find()->where(['meeting_id'=>$id]), |
3 |
'sort' => [ |
4 |
'defaultOrder' => [ |
5 |
'availability'=>SORT_DESC |
6 |
]
|
7 |
],
|
8 |
]);
|
9 |
$placeProvider = new ActiveDataProvider([ |
10 |
'query' => MeetingPlace::find()->where(['meeting_id'=>$id]), |
11 |
'sort' => [ |
12 |
'defaultOrder' => [ |
13 |
'availability'=>SORT_DESC |
14 |
]
|
15 |
],
|
16 |
]);
|
Makikita mo ang mga akto na ito na nasa ibaba na planning screenshot:



Para masubaybayan kung ang kalahok ay taga- organisa at para mapahintulutan para sa panghinaharap na mapiling hindi maisama sa partikular na abiso ng pulong, Idinagdag ko ang migration na ito para Participant table:
1 |
<?php
|
2 |
|
3 |
use yii\db\Schema; |
4 |
use yii\db\Migration; |
5 |
|
6 |
class m160825_074740_extend_participant_add_type extends Migration |
7 |
{
|
8 |
public function up() |
9 |
{
|
10 |
$tableOptions = null; |
11 |
if ($this->db->driverName === 'mysql') { |
12 |
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; |
13 |
}
|
14 |
$this->addColumn('{{%participant}}','participant_type',Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0'); |
15 |
$this->addColumn('{{%participant}}','notify',Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0'); |
16 |
}
|
17 |
|
18 |
public function down() |
19 |
{
|
20 |
$this->dropColumn('{{%participant}}','participant_type'); |
21 |
$this->dropColumn('{{%participant}}','notify'); |
22 |
}
|
23 |
}
|
Nagdagdag din ako ng mga number of constants sa Participant.php upang makapag-trabaho sa mga properties na ito:
1 |
class Participant extends \yii\db\ActiveRecord |
2 |
{
|
3 |
const TYPE_DEFAULT = 0; |
4 |
const TYPE_ORGANIZER = 10; |
5 |
|
6 |
const NOTIFY_ON = 0; |
7 |
const NOTIFY_OFF = 1; |
8 |
|
9 |
const STATUS_DEFAULT = 0; |
10 |
const STATUS_REMOVED = 90; |
11 |
const STATUS_DECLINED = 100; |
12 |
const STATUS_DECLINED_REMOVED = 110; |
At alam kong makakatulong kung meron
pang ibang makatuwang sa pagtitipon sa loob ng naglalakihang modelo ng pulong.
Halimbawa, IsOrganizer ()
nagsasabi sa akin kung ang kasalukuyang tumitingin
ay isang taga-organiza ng pulong:
1 |
public function isOrganizer() { |
2 |
$user_id = Yii::$app->user->getId(); |
3 |
if ($user_id == $this->owner_id) { |
4 |
return true; |
5 |
} else { |
6 |
foreach ($this->participants as $p) { |
7 |
if ($user_id == $p->participant_id) { |
8 |
if ($p->participant_type == Participant::TYPE_ORGANIZER) { |
9 |
return true; |
10 |
} else { |
11 |
return false; |
12 |
}
|
13 |
}
|
14 |
}
|
15 |
}
|
16 |
return false; |
17 |
}
|
Saglit, meron pa?
Gaya ng iyong nakikita, Marami pang dapat sakupin upang mabuo ang tampok na ito. Sa susunod na kabanata, Aking sasakupin and ikalawang hati ng pagbuo at pagsubok na kinakailangan upang mai-sulong ang maramihang kalahok sa pulong: hanay ng tatanggap, abiso, kahilingan, at pagtugon sa mga kahilingan.
Kung wala ka pa, mag iskedyul ka ng iyong unang pulong sa taga-plano ng pulong at subukan itong lahat. Pakiusap na sanaý ibahagi ang inyong katugunan sa mga komento sa ilalim.
Pagtuturo ng crowdfunding ay inuumpisahan na, kung kaya’t sana ay sundan nyo ang aming WeFunder Meeting Planner pahina.
Maari nyo rin akong maabot sa @reifman. Akoý
laging bukas para sa mga bagong tampok na mga ideya at mga mungkahing paksa
para sa panghinaharap na pagtuturo.
Hintayin lamang ang lahat ng mga ito at marami pang mga darating na pagtuturo sa pamamagitan ng pagtingin sa Building Your Startup With PHP series.