Статьи

Создание вашего стартапа: доставка приглашения на встречу

Конечный продукт
Что вы будете создавать

Это руководство является частью серии « Создай свой стартап с помощью PHP» на Envato Tuts +. В этой серии я проведу вас через запуск стартапа от концепции до реальности, используя мое приложение Meeting Planner в качестве примера из реальной жизни. На каждом этапе я буду публиковать код Планировщика собраний в качестве примеров с открытым исходным кодом, из которых вы можете извлечь уроки. Я также буду решать вопросы, связанные с бизнесом по мере их возникновения

В этом учебном пособии мы расскажем об отправке приглашения участнику по электронной почте, реализации основного вида его содержимого и рассмотрении создания ссылок для получателей, чтобы они могли ответить.

Весь код для Meeting Planner написан на Yii2 Framework для PHP. Если вы хотите узнать больше об Yii2, ознакомьтесь с серией моих параллельных программ по программированию на Yii2 в Envato Tuts +.

Просто напоминание, я участвую в комментариях ниже. Мне особенно интересно, если у вас есть другие подходы, дополнительные идеи или вы хотите предложить темы для будущих уроков. Вы также можете связаться со мной в Twitter @reifman .

Очень интересно достичь этой стадии доставки первых приглашений, но это все еще требует большой работы. В последнем эпизоде я обновил представления собраний, чтобы они могли поддерживать либо организатора, либо участников.

Большая часть работы в этом эпизоде ​​будет сосредоточена на создании электронных писем HTML в Yii и их доставке программно. Однако, когда я начал писать код для этого, я столкнулся со всеми сложностями, которые система должна вскоре поддержать. Например, все ссылки в приглашениях необходимы для безопасной аутентификации участников, учитывая, что они никогда не регистрировались в Meeting Planner. Часть этого я сохраню для следующего эпизода.

По сути, мы должны уведомить приложение о том, кто просматривает страницу собрания, а затем настроить внешний вид и доступные команды. Yii делает большую часть этого довольно простым, но в нем много деталей.

Краткая оговорка об опыте пользователя

Прежде всего позвольте мне сказать, что на пути к созданию минимально жизнеспособного продукта (MVP) потребуется много времени для доработки и доработки пользовательского опыта. Большая часть того, что я сейчас создаю, — это основная функциональность, позволяющая запустить альфа-версию для реального использования. Я знаю, что это выглядит грубым в некоторых местах и ​​не всегда будет казаться таким интуитивным, как вы хотите. Есть также недостатки кодирования, которые необходимо будет оптимизировать в будущем.

Пожалуйста, не стесняйтесь оставлять свои мысли и комментарии ниже, и я буду принимать их во внимание для дальнейшей работы.

Вот некоторые из проблем, которые возникли с работой этого эпизода:

  • Основной дизайн и содержание приглашения по электронной почте
  • Как будут доставляться приглашения? например, какая платформа электронной почты или провайдер?
  • Какие связанные команды будут предложены в письме? И сможет ли организатор ограничить некоторые полномочия, предоставляемые участникам?
  • Функциональный ответ на связанные команды в приглашении по электронной почте
  • Управление посещениями приглашенных пользователей, которые еще не зарегистрировались, например, что они могут получить и не могут?
  • Обработка пользовательского опыта для сбора дружественных имен от посетителей
  • Регистрация ответов на приглашение на собрание, а затем наращивание возможностей мониторинга и уведомлений для информирования организатора.
  • Планирование инфраструктуры для будущих электронных писем, показывающих обновления по мере изменения конфигурации собрания и по мере того, как время приближается (и проходит), например, уведомления об изменениях, напоминания о собраниях, принятие ответов в виде новых заметок и т. Д.

Когда я писал код для этого эпизода, я создал некоторую инфраструктуру для некоторых из вышеперечисленных пунктов и оставил некоторые из них для обсуждения в будущих эпизодах. Для начала давайте погрузимся в дизайн приглашения.

Сначала я должен был спросить, что должно быть включено в электронное письмо? Очевидно, были бы стандартные поля:

  • к
  • Из
  • Тема ( вы приглашены на встречу! )
  • Тело сообщения
  • нижний колонтитул

Содержание тела должно включать:

  • Детали встречи
  • Предлагаемые места
  • Предлагаемые даты и время

И, в зависимости от настроек органайзера, какие командные ссылки должны быть представлены? Вот несколько вопросов, которые возникли. Должны ли мы разрешить получателям:

  • Принять каждый вариант, то есть все места, даты и время являются приемлемыми
  • Принять все места или все даты и время отдельно
  • Принять конкретные места и конкретные даты и время индивидуально
  • См карты для предполагаемых мест и в конечном итоге веб-сайтов и ссылок Yelp
  • Отправить заметку организатору для просмотра собрания
  • Предложить новое место или дату и время
  • Выберите место или дату и время
  • Завершить встречу

Наконец, нижний колонтитул должен будет поддерживать:

  • Альфа-уведомление с запросом обратной связи
  • Возможность заблокировать отправителя
  • Возможность отписаться от будущих приглашений Планировщика собраний
  • Информация о компании и контактная информация

Я знаю, что все это может быть сложно визуализировать — это был непростой эпизод для создания. Вот пример приглашения, которое я в конечном итоге создал:

Пример приглашения для планирования встречи

На данный момент я использовал команды, приемлемые и отклоняющие, чтобы указать участнику, что они просто указывают, работает ли для них место или дата и время или нет. Однако для простоты я предложил Примите все места и время , примите все места и примите все время, чтобы управлять этим в более быстрых шагах.

Все это в значительной степени основано на фактической форме приглашения на встречу из последнего эпизода. Ниже вы можете увидеть часть приглашения, которая предлагает конфигурацию мест и времени:

Приглашение для встречи - Просмотр мест и времени

Обратите внимание, что электронная почта предоставляет некоторые расширенные функциональные возможности, которые были созданы в последнем эпизоде, что позволяет организаторам предлагать участникам расширенные уровни контроля, такие как предложение новых мест и времени, выбор конечного места и времени и т. Д.

Приглашение для планирования встречи - обновление настроек встречи

Мне очень быстро стало очевидно, что в будущем потребуются дополнительные инвестиции в разработку электронной почты и предложение более простых конфигураций приглашения. Опять же, мне придется сохранить это для будущих эпизодов.

Например, один из моих первых друзей по альфа-тестированию предложил, чтобы они могли указать, что некоторые места работают только в определенные даты и время, и наоборот. В конечном счете, мне может понадобиться объединить места, даты и время в одну модель выбора.

А пока давайте рассмотрим, как я доставил вышеупомянутое приглашение, как оно есть.

Приглашение организатора собраний - панель команд с отправкой

Что происходит, когда организатор нажимает кнопку Отправить ? Сначала я ожидал, что мне придется писать напрямую в API Mailgun, который я изучал в предыдущих уроках Envato Tuts + . Тем не менее, поддержка электронной почты в Yii2 довольно обширна , и я смог использовать встроенную поддержку представлений для макетов электронной почты (как HTML, так и текста) и просто доставить их с помощью аутентификации моей учетной записи Mailgun SMTP. Это даже поддерживает прикрепление файлов будущих событий (.ics) для импорта собраний в календари.

Примечание: я большой поклонник Mailgun, но я также занимался разработкой для них в качестве консультанта и написал для их блога и Envato Tuts + .

Прежде чем продолжить, я призываю вас взглянуть на документацию по рассылке Yii2 . Он предлагает отличный обзор.

Сначала я добавил более подробные параметры конфигурации SwiftMailer в /common/config/main-local.php:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
return [
    ‘components’ => [
        ‘db’ => [
            ‘class’ => ‘yii\db\Connection’,
            ‘dsn’ => ‘mysql:host=localhost;dbname=mp’,
            ‘username’ => ‘xxxxxxxxxxxx’,
            ‘password’ => ‘xxxxxxxxxxxx’,
            ‘charset’ => ‘utf8’,
        ],
        ‘mailer’ => [
            ‘class’ => ‘yii\swiftmailer\Mailer’,
            ‘viewPath’ => ‘@common/mail’,
            //comment the following array to send mail using php’s mail function
            ‘transport’ => [
                ‘class’ => ‘Swift_SmtpTransport’,
                ‘host’ => ‘smtp.mailgun.org’,
                ‘username’ => ‘[email protected]’,
                ‘password’ => ‘axxxxxxxxxxxxxxxxxxxxxxxx2’,
                ‘port’ => ‘587’,
                ‘encryption’ => ‘tls’,
                            ],
            // send all mails to a file by default.
            // ‘useFileTransport’ to false and configure a transport
            // for the mailer to send real emails.
            ‘useFileTransport’ => false,
        ],
    ],
];

Это позволило компоненту Yii SwiftMailer доставлять мои электронные письма через базовый SMTP-сервис Mailgun .

Вам необходимо получить настройки SMTP Mailgun из панели управления вашего домена:

Приглашение для планирования встречи - настройки SMTP Mailgun

Конечно, вы также должны убедиться, что SwiftMailer является частью вашей конфигурации файла composer.json, прежде чем запускать composer update :

1
2
3
4
5
6
«minimum-stability»: «stable»,
   «require»: {
       «php»: «>=5.4.0»,
       «yiisoft/yii2»: «>=2.0.7»,
       «yiisoft/yii2-bootstrap»: «*»,
       «yiisoft/yii2-swiftmailer»: «*»,

Затем я создал конфигурацию файла представления для использования SwiftMailer. Во-первых, должен быть основной макет для HTML и текста. Затем должны быть отдельные файлы контента для каждого:

Приглашение организатора собрания - папка и файлы в почтовых макетах

Не все это полностью задокументировано для Yii, так что, надеюсь, этот пример предложит некоторые рекомендации. Обратите внимание, что файлы вида finalize-html и -text были добавлены позже для будущего эпизода.

Как правило, файл layouts / html.php довольно прост:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
use yii\helpers\Html;
 
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Strict//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
    <meta http-equiv=»Content-Type» content=»text/html; charset=<?= Yii::$app->charset ?>» />
    <style type=»text/css»>
        .heading {…}
        .list {…}
        .footer {…}
    </style>
    <?php $this->head() ?>
</head>
<body>
    <?php $this->beginBody() ?>
    <?= $content ?>
    <div class=»footer»>With kind regards, <?= Yii::$app->name ?> team</div>
    <?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

Тем не менее, я многое добавил к нему, чтобы начать работать со стилем и форматированием электронных писем в формате HTML, предлагаемых сообществу открытого исходного кода Mailchimp .

Yii’s SwiftMailer, как правило, автоматически конвертирует ваш HTML-вид в текст-совместимые для вас. Скорее всего, я буду хотеть более короткое и более простое текстовое представление для приглашений, но сейчас я собираюсь отложить просмотр результатов моего кода, основанных на текстовой электронной почте.

В модели Meeting.php я написал функцию отправки, которая собирает все данные, необходимые для построения моего представления приглашения, показанного выше. На данный момент я опускаю части, связанные со следующим эпизодом для создания командных ссылок. В основном я использую Yii :: $ app-> mailer compose () и send () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public function send($user_id) {
   …
 foreach ($this->participants as $p) {
   …
   // send the message
   $message = Yii::$app->mailer->compose([
     ‘html’ => ‘invitation-html’,
     ‘text’ => ‘invitation-text’
   ],
   [
     ‘meeting_id’ => $this->id,
     ‘noPlaces’ => $noPlaces,
     ‘participant_id’ => 0,
     ‘owner’ => $this->owner->username,
     ‘user_id’ => $p->participant_id,
     ‘auth_key’ => $auth_key,
     ‘intro’ => $this->message,
     ‘links’ => $links,
     ‘header’ => $header,
     ‘places’ => $places,
     ‘times’ => $times,
     ‘notes’ => $notes,
     ‘meetingSettings’ => $this->meetingSettings,
 ]);
   // to do — add full name
   $message->setFrom(array(‘[email protected]’=>$this->owner->email));
   $message->setTo($p->participant->email)
       ->setSubject(Yii::t(‘frontend’,’Meeting Request: ‘).$this->subject)
       ->send();
 }
 …

Эти функции создают сообщение с использованием нашего HTML-макета и просмотра, а затем передают полученные сообщения с персонализированными данными службе SMTP Mailgun. Мы можем использовать реализацию Yii своей модели MVC для доставки электронной почты.

Поскольку я использовал Composer с Yii, я часто сталкиваюсь с множеством проблем, которые трудно отследить. Чаще всего это связано с тем, что плагину «yiisoft / yii2-composer» требуется ошибка composer-plugin-api 1.0.0 , но на этот раз я столкнулся с проблемой обновления Mailgun. Последние версии Mailgun API требуют текущих обновлений для guzzle. Более ранний плагин Yii, используемый в MeetingPlanner, требовал исправленной, устаревшей версии жадности. Итак, мне пришлось настроить композитор для использования псевдонима.

По сути, я дал указание композитору синхронизировать последнюю версию guzzle, но сообщить приложению, что оно использовало более старую версию. В composer.json псевдоним выглядит так:

1
2
3
4
5
«yiisoft/yii2-authclient»: «~2.0.0»,
«mailgun/mailgun-php»: «~2.0»,
«guzzlehttp/guzzle»:»6.2.0 as 4.2.3″,
«php-http/guzzle6-adapter»:»1.0.0″
},

Я приказываю ему установить «guzzlehttp / guzzle»: «6.2.0 as 4.2.3», и это заставляет все работать хорошо, по крайней мере, в этом случае. Иногда разработчики плагинов требуют определенных версий библиотек для правильной работы. Композитор, в основном, полезен, но иногда это действительно весело.

Поэкспериментировав с приглашениями, я решил настроить представление создания собрания, чтобы более четко поддерживать предметную область. Это позволяет пользователям написать строку темы, как если бы они отправляли электронное письмо, чтобы пригласить кого-либо на собрание без Планировщика собраний. UX для этого нужно будет со временем повторять и упрощать.

Приглашение организатора собраний - создание собрания

Это обеспечивает идеальную строку темы в электронном письме для приглашения на встречу. Конечно, чтобы обеспечить это, мне пришлось расширить модель Встречи.

Я создал новую миграцию под названием extend_meeting_table_add_subject который добавил предметную область:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
 
use yii\db\Schema;
use yii\db\Migration;
 
class m160409_204159_extend_meeting_table_add_subject extends Migration
{
  public function up()
  {
    $tableOptions = null;
    if ($this->db->driverName === ‘mysql’) {
        $tableOptions = ‘CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB’;
    }
 
    $this->addColumn(‘{{%meeting}}’,’subject’,’string NOT NULL’);
  }
 
  public function down()
  {
    $this->dropColumn(‘{{%meeting}}’,’subject’);
  }
}

И мне пришлось добавить поддержку нового поля в файл Meeting _form.php и модель.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<div class=»meeting-form»>
 
    <?php $form = ActiveForm::begin();
 
    <?= $form->field($model, ‘meeting_type’)
            ->dropDownList(
                $model->getMeetingTypeOptions(),
                [‘prompt’=>Yii::t(‘frontend’,’What type of meeting is this?’)]
            )->label(Yii::t(‘frontend’,’Meeting Type’)) ?>
 
    <?= $form->field($model, ‘subject’)->textInput([‘maxlength’ => 255])->label(Yii::t(‘frontend’,’Subject’)) ?>
 
    <?= $form->field($model, ‘message’)->textarea([‘rows’ => 6])->label(Yii::t(‘frontend’,’Message’))->hint(Yii::t(‘frontend’,’Optional’)) ?>
 
    <div class=»form-group»>
        <?= Html::submitButton($model->isNewRecord ? Yii::t(‘frontend’, ‘Create’) : Yii::t(‘frontend’, ‘Update’), [‘class’ => $model->isNewRecord ? ‘btn btn-success’ : ‘btn btn-primary’]) ?>
    </div>
 
    <?php ActiveForm::end();
 
</div>

Вот выдержка из того, что добавлено в модель Meeting.php:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public function rules()
   {
       return [
           [[‘owner_id’, ‘subject’], ‘required’],
           [[‘owner_id’, ‘meeting_type’, ‘status’, ‘created_at’, ‘updated_at’], ‘integer’],
           [[‘message’,’subject’], ‘string’]
       ];
   }
 
   /**
    * @inheritdoc
    */
   public function attributeLabels()
   {
       return [
           ‘id’ => Yii::t(‘frontend’, ‘ID’),
           ‘owner_id’ => Yii::t(‘frontend’, ‘Owner ID’),
           ‘meeting_type’ => Yii::t(‘frontend’, ‘Meeting Type’),
           ‘subject’ => Yii::t(‘frontend’, ‘Subject’),
           ‘message’ => Yii::t(‘frontend’, ‘Message’),
           ‘status’ => Yii::t(‘frontend’, ‘Status’),
           ‘created_at’ => Yii::t(‘frontend’, ‘Created At’),
           ‘updated_at’ => Yii::t(‘frontend’, ‘Updated At’),
       ];
   }

Изначально ссылки на мою карту приглашений шли непосредственно на Google Maps, но я понял, что было бы лучше связать их со встроенным представлением карты в Планировщике собраний, которое было частью приглашения на собрание. В моем случае я создал вид карты с помощью кнопки «Вернуться к совещанию»:

Приглашение для встречи - Просмотр места в приглашении на встречу

Для этого я создал новый вид, основанный на /views/place/view.php. Вот /views/meeting/viewplace.php:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
 
use dosamigos\google\maps\Map;
use dosamigos\google\maps\LatLng;
use dosamigos\google\maps\overlays\Marker;
use yii\helpers\Html;
use yii\widgets\DetailView;
 
/* @var $this yii\web\View */
/* @var $model frontend\models\Place */
$this->title = $model->getMeetingHeader();
$this->params[‘breadcrumbs’][] = [‘label’ => Yii::t(‘frontend’, ‘Meetings’), ‘url’ => [‘index’]];
$this->params[‘breadcrumbs’][] = $this->title;
$this->params[‘breadcrumbs’][] = $place->name;
?>
<h1><?php echo Html::encode($this->title) ?></h1>
 
<p>
  <?php echo Html::a(Yii::t(‘frontend’, ‘Return to Meeting’), [‘view’, ‘id’ => $model->id], [‘class’ => ‘btn btn-primary’]) ?>
</p>
 
<div class=»col-md-6″>
<div class=»place-view»>
 
    <?php echo DetailView::widget([
        ‘model’ => $place,
        ‘attributes’ => [
            ‘name’,
            [‘label’ => ‘website’,
     ‘value’ => Html::a($place->website, $place->website),
     ‘format’ => ‘raw’],
            //’place_type’,
            ‘full_address’,
        ],
    ]) ?>
 
</div>
</div> <!— end first col —>
<div class=»col-md-6″>
  <?php
  if ($gps!==false) {
    $coord = new LatLng([‘lat’ => $gps->lat, ‘lng’ => $gps->lng]);
    $map = new Map([
        ‘center’ => $coord,
        ‘zoom’ => 14,
        ‘width’=>300,
        ‘height’=>300,
    ]);
    $marker = new Marker([
        ‘position’ => $coord,
        ‘title’ => $place->name,
    ]);
    // Add marker to the map
    $map->addOverlay($marker);
    echo $map->display();
  } else {
    echo ‘No location coordinates for this place could be found.’;
  }
  ?>
 
</div> <!— end second col —>

Как видите, получение первого приглашения по электронной почте вызвало множество проблем и потребовало много небольших и средних обновлений. Но, имея базовую основу для них, мы можем рассмотреть сложность того, что было создано. Другими словами, что нужно дальше:

  • Аутентифицированные командные ссылки. Когда участник щелкает ссылку команды в сообщении электронной почты, как мы будем аутентифицировать его, особенно если он никогда не регистрировался в нашем приложении?
  • Завершение встречи на основе ответов. Когда участники делают выбор, и организатор готов завершить собрание, какие изменения и обновления необходимы для его поддержки?
  • Мониторинг процесса внесения изменений участниками в приглашение. Как мы будем отслеживать изменения в деталях встречи и выбирать, когда следует уведомлять организаторов и участников?
  • Уведомление организатора и участника об изменениях. Что мы должны им сказать, и какие варианты должны быть предложены, когда мы уведомим их?
  • Создание файлов Календаря (.ics) для импорта в Календарь Google, Outlook и Apple Calendar с подробной информацией о приглашении. После завершения собрания мы можем отправить загружаемый файл .ics.
  • Создание представления о встрече, которая полностью завершена. Как должны выглядеть детали встречи, когда ей больше не нужно предлагать команды для выбора мест и времени? Но также, какие команды необходимы для перепланирования, сдвига времени, отмены, изменения местоположения или даты и времени и т. Д.?

В следующем эпизоде ​​мы рассмотрим некоторые из этих вопросов, сосредоточив внимание на ссылках в приглашении, на которые получатели захотят ответить, несмотря на то, что изначально они никогда не регистрировались в Meeting Planner. Другие вопросы придется подождать немного дольше.

Я также начинаю экспериментировать с WeFunder, основываясь на внедрении новых правил краудфандинга SEC . Пожалуйста, обратите внимание на наш профиль . Я могу написать об этом больше как часть этой серии.

Следите за будущими уроками в моей серии «Построение стартапа с помощью PHP» — надеюсь, вы согласитесь, что это становится захватывающим!

Пожалуйста, не стесняйтесь добавлять свои вопросы и комментарии ниже; Я обычно участвую в обсуждениях. Вы также можете связаться со мной в Twitter @reifman .