Uw startproces opbouwen herinneringen verzenden

Wat je gaat creëren

Deze tutorial maakt deel uit van de Build Your Startup With PHP-serie op Envato Tuts +. In deze serie begeleid ik je door een opstart van concept naar realiteit te starten met behulp van mijn Meeting Planner-app als een realistisch voorbeeld. Elke stap die ik doe, zal ik de Meeting Planner-code vrijgeven als open-source voorbeelden waar je van kunt leren. Ik zal ook opstartgerelateerde zakelijke problemen aanpakken zodra deze zich voordoen.

In deze tweedelige tutorial beschrijf ik hoe ik de infrastructuur voor herinneringen en de levering ervan heb gebouwd. Vandaag zal ik u helpen bij het monitoren wanneer u herinneringen moet sturen en hoe u de e-mails kunt verzenden.

Als u Meeting Planner nog niet hebt uitgeprobeerd, kunt u uw eerste vergadering plannen. Ik neem wel deel aan de opmerkingen hieronder, dus vertel me wat je denkt! Ik ben vooral geïnteresseerd als u nieuwe functies of onderwerpen voor toekomstige zelfstudies wilt voorstellen.

Ter herinnering: alle code voor Meeting Planner is geschreven in het Yii2 Framework voor PHP. Als je meer wilt weten over Yii2, bekijk dan onze parallelle serie Programming With Yii2.

Monitoring tijd voor herinneringen

Naarmate de tijd verstrijkt, moeten we waken over de MeetingReminder tabel om te weten wanneer herinneringen moeten worden afgeleverd. Idealiter willen we dat herinneringen precies op tijd worden afgeleverd, bijvoorbeeld tot op de minuut.

Achtergrondtaken uitvoeren

De tijdigheid is afhankelijk van hoe regelmatig we achtergrondtaken uitvoeren voor monitoring. Momenteel voer ik ze in onze pre-alfa-fase elke vijf minuten uit:

# m h dom mon dow-opdracht * / 5 * * * * wget -O / dev / null http://meetingplanner.io/daemon/frequent

Dit script roept MeetingReminder :: cheque (), die vergaderherinneringen vindt die moeten worden ontvangen en waarvoor een verzoek moet worden gedaan werkwijze() hen:

// frequente cron-taak belt om te controleren op gepaste herinneringen openbare statische functiecontrole () $ mrs = MeetingReminder :: find () -> where ('due_at<='.time().' and status='.MeetingReminder::STATUS_PENDING)->allemaal(); foreach ($ mrs as $ mr) // verwerk elke herinnering voor een vergadering MeetingReminder :: process ($ mr); 

Een herinnering verwerken

MeetingReminder :: proces () verzamelt de gegevens die nodig zijn om een ​​herinneringsmail te maken. Dit omvat de ontvanger van de herinnering, de details van de vergadering en de tijd:

openbaar statisch functieproces ($ mr) // haal de herinnering op // bezorg de e-mail of sms // stuur updates over recente wijzigingen in de vergadering gemaakt door $ user_id $ user_id = $ mr-> user_id; $ meeting_id = $ mr-> meeting_id; $ mtg = Meeting :: findOne ($ meeting_id); // stuur alleen herinneringen voor vergaderingen die worden bevestigd als ($ mtg-> status! = Meeting :: STATUS_CONFIRMED) false retourneert; // stuur alleen herinneringen die minder dan een dag te laat zijn - om te doen - verwijder na testperiode als ((tijd () - $ mr-> due_at)> (24 * 3600 + 1)) false retourneert; $ u = \ common \ models \ User :: findOne ($ user_id); // zorg dat er een auth-sleutel is voor de ontvanger-gebruiker als (leeg ($ u-> auth_key)) return false;  // gegevens voorbereiden voor het bericht // tijd krijgen $ selected_time = Meeting :: getChosenTime ($ meeting_id); $ timezone = MiscHelpers :: fetchUserTimezone ($ user_id); $ display_time = Meeting :: friendlyDateFromTimestamp ($ selected_time-> start, $ timezone); // plaats krijgen $ chosen_place = Meeting :: getChosenPlace ($ meeting_id); $ a = ['user_id' => $ user_id, 'auth_key' => $ u-> auth_key, 'email' => $ u-> email, 'gebruikersnaam' => $ u-> gebruikersnaam]; // controleer of e-mail in orde is en ok van deze sender_id indien (User :: checkEmailDelivery ($ user_id, 0)) // Bouw de absolute links naar de vergadering en commandeert $ links = ['home' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_HOME, 0, $ a ['user_id'], $ a ['auth_key']), 'view' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_VIEW, 0, $ a ['user_id'], $ a ['auth_key']), 'footer_email' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_FOOTER_EMAIL, 0, $ a ['user_id' ], $ a ['auth_key']), 'footer_block' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_FOOTER_BLOCK, 0, $ a ['user_id'], $ a ['auth_key']) , 'footer_block_all' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_FOOTER_BLOCK_ALL, 0, $ a ['user_id'], $ a ['auth_key']), 'running_late' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_RUNNING_LATE, 0, $ a ['user_id'], $ a ['auth_key']), 'view_map' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_VIEW_MAP, 0, $ a ['user_id'], $ a ['auth_key'])]; // stuur het bericht $ message = Yii :: $ app-> mailer-> compose (['html' => 'reminder-html', 'text' => 'reminder-text'], ['meeting_id' => $ mtg-> id, 'sender_id' => $ user_id, 'user_id' => $ a ['user_id'], 'auth_key' => $ a ['auth_key'], 'display_time' => $ display_time, 'chosen_place '=> $ selected_place,' links '=> $ links,' meetingSettings '=> $ mtg-> meetingSettings,]); if (! empty ($ a ['email'])) $ message-> setFrom (['[email protected]' => 'Meeting Planner']); $ message-> setTo ($ a ['email']) -> setSubject (Yii :: t ('frontend', 'Meeting Reminder:'). $ mtg-> onderwerp) -> send ();  $ mr-> status = MeetingReminder :: STATUS_COMPLETE; $ MR-> update ();  

De Gebruikers :: checkEmailDelivery () functie controleert of de gebruiker geen e-mails van het systeem (of van bepaalde personen) heeft geblokkeerd. Het zorgt ervoor dat het goed is om de herinnering te verzenden:

// controleer of e-mail in orde is en ok van deze sender_id indien (User :: checkEmailDelivery ($ user_id, 0)) // Bouw de absolute links naar de vergadering en commandeert $ links = ['home' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_HOME, 0, $ a ['user_id'], $ a ['auth_key']), 'view' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_VIEW, 0, $ a ['user_id'], $ a ['auth_key']), 'footer_email' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_FOOTER_EMAIL, 0, $ a ['user_id' ], $ a ['auth_key']), 'footer_block' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_FOOTER_BLOCK, 0, $ a ['user_id'], $ a ['auth_key']) , 'footer_block_all' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_FOOTER_BLOCK_ALL, 0, $ a ['user_id'], $ a ['auth_key']), 'running_late' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_RUNNING_LATE, 0, $ a ['user_id'], $ a ['auth_key']), 'view_map' => MiscHelpers :: buildCommand ($ mtg-> id, Meeting :: COMMAND_VIEW_MAP, 0, $ a ['user_id'], $ a ['auth_key'])]; 

Hier is de Gebruikers :: checkEmailDelivery methode. Eerst wordt gecontroleerd of de gebruiker alle e-mail volledig heeft geblokkeerd (hopelijk niet) of dat het bericht is verzonden van een geblokkeerde gebruiker:

 openbare statische functie checkEmailDelivery ($ user_id, $ sender_id) // controleer of deze user_id e-mail ontvangt en of sender_id niet geblokkeerd wordt // controleer of alle e-mail is uitgeschakeld $ us = UserSetting :: safeGet ($ user_id); if ($ us-> no_email! = UserSetting :: EMAIL_OK) return false;  // controleer of er geen verzender, d.w.z. systeemmelding als ($ sender_id == 0) return true;  // controleer of verzender geblokkeerd is $ ub = UserBlock :: find () -> where (['user_id' => $ user_id, 'blocked_user_id' => $ sender_id]) -> one (); if (! is_null ($ ub)) return false;  return true;  

De nieuwe e-mailsjabloon voor herinneringen

In de afleveringsbijeenkomst Delivering Your Meeting Invitation schreef ik over het verzenden van e-mailberichten binnen het Yii Framework. Bij het verfijnen van e-mailsjablonen, beschreef ik het bijwerken van de sjablonen voor onze nieuwe, op Oxygen gebaseerde, responsieve sjablonen.

Dit is de nieuwe e-mailsjabloon reminder_html.php:

   
Herinnering aan uw vergadering
Gewoon een herinnering over je aanstaande vergadering op plaats-> name; ?> (plaats-> omgeving; ?>, ) via telefoon of videoconferentie.
Klik hieronder om meer details te bekijken om de vergaderingpagina te bekijken.
"> Bezoek de vergaderingpagina
Handige opties:

view-> renderFile ('@ common / mail / sectie-footer-dynamic.php', ['links' => $ links])?>

Het bevat de datum, tijd en gekozen locatie (met een adres- en kaartlink). Ik heb ook het begin van een nuttig optiesgebied toegevoegd met een eerste opdracht: "Informeer hen dat ik te laat ben":

Wanneer er op wordt geklikt, e-mailen of sms'en we de andere deelnemer (s) dat u mogelijk vijf tot tien minuten te laat bent. Er is niets anders te doen of te typen terwijl je haast hebt.

Misschien zal een eventuele mobiele versie van Meeting Planner uw GPS-locatie kennen en hen ongeveer laten weten hoe ver u zich bevindt. Ik ben begonnen met het volgen van ideeën zoals deze in Asana voor productplanning - ik zal de Envato Tuts + redactionele godinnen vragen (hieronder weergegeven) als ik in een toekomstige zelfstudie kan schrijven over het implementeren van functies en het volgen van problemen..

Verbeteringen voor herinneringen

De herinneringse-mail kan eigenlijk een paar verbeterde functies gebruiken:

  • Het voltooien van de lopende late e-mailimplementatie.
  • Contactinformatie van andere deelnemers weergeven, zoals telefoonnummers en e-mailadressen. De running late email kan alleen de contactgegevens tonen van de persoon die te laat is.
  • Geef een statische Google-kaart weer met de locatie van de vergadering.
  • Koppelen aan een functie om een ​​verzoek in te dienen of een herschikking van de vergadering vereisen.
  • Link naar niet alleen de kaart, maar ook de routebeschrijving naar de locatie.
  • Link om uw herinneringen aan te passen.

Het blijkt dat de meeste van deze functies meer werk vereisen dan er ruimte is voor in deze zelfstudie. 

Bijvoorbeeld, het idee om een ​​lopende e-mail te sturen lijkt een eenvoudige functie, toch? Het is een goed voorbeeld van de uitdaging die MVC-frameworks soms opleggen aan ontwikkelaars. Het implementeren van een running late email-functie vereist code voor een aantal bestanden, inclusief een nieuwe e-mailsjabloon.

Implementatie van de Running Late Feature

In plaats van alle codeveranderingen te delen die voor deze functie vereist zijn, vat ik alleen de plaatsen samen waar verandering nodig was rond het kader:

  • De herinneringse-mail had een link nodig met een nieuwe opdracht
  • De COMMAND_RUNNING_LATE moest worden gedefinieerd in het Meeting-model en controller, en het moest een bevestigingsbericht weergeven.

Hier is een voorbeeld van wat u ziet nadat u heeft gevraagd om een ​​te late kennisgeving te verzenden:

  • De sendLateNotice () methode moest worden gebouwd in Meeting.php
  • De late-html.php e-mailsjabloon moest worden gebouwd. Dit omvat een optie voor de andere deelnemer om aan te kondigen dat ze ook 'te laat' zijn.
  • De UserContact :: buildContactString () methode moest worden aangevuld met contactgegevens van de persoon die te laat was.
  • De ACTION_SENT_RUNNING_LATE moest worden aangemaakt om het verzenden van een late kennisgeving namens deze persoon in het MeetingLog vast te leggen.
  • De sendLateNotice () methode moest het log controleren en een fout weergeven als de late kennisgeving al een keer was verzonden.

Dit is wat de late melding die al is verzonden, wordt weergegeven: 

Het was veel code om te implementeren wat leek op een eenvoudige toevoeging. 

Ik wachtte om de functie te testen totdat alle bovenstaande wijzigingen waren aangebracht en ik was aangenaam verrast dat ze allemaal precies werkten zoals bedoeld. Ik hoefde maar een paar cosmetische wijzigingen aan de tekst aan te brengen.

Implementatie van weergave van contactgegevens van deelnemers

Hoewel deze functie al bestond voor iCal-bestanden, moest ik deze functie voltooien voor uitnodigingen via e-mail. Dus ik heb uitgebreid UserContact :: buildContactString ($ user_id, $ mode) voor $ Mode = 'html'.

Hier is de bijgewerkte code:

openbare statische functie buildContactString ($ user_id, $ mode = 'ical') // te doen - maak hier een weergave van die kan worden weergegeven $ contacts = UserContact :: getUserContactList ($ user_id); if (count ($ contacts) == 0) return "; if ($ mode == 'ical') $ str =";  else if ($ mode == 'html') $ str = '

'; $ str = \ common \ components \ MiscHelpers :: getDisplayName ($ user_id). ':'; if ($ mode == 'ical') $ str. = '\\ n'; else if ($ mode == 'html') $ str. = '
'; foreach ($ contacten als $ c) if ($ mode == 'ical') $ str. = $ c-> friendly_type. ':'. $ c-> info. ' (' $ C-> details.. ') \\ n'; else if ($ mode == 'html') $ str. = $ c-> friendly_type. ':'. $ c-> info. '
'$ C-> details.'
'; if ($ mode == 'ical') $ str. = '\\ n'; else if ($ mode == 'html') $ str. = '

'; return $ str;

Ik ben er zeker van dat het wat moet worden opgepoetst als we naar alfa- en bètatests gaan, maar de functionaliteit is er nu.

U kunt de contactgegevens in de volledige late kennisgeving hierboven zien, maar hier is het segment dat wordt gegenereerd:

Polijst herinneringen

Met deze late mini-functies ging het zo goed dat ik de link heb toegevoegd om je herinneringen aan te passen aan de oorspronkelijke herinneringse-mail.

Met al deze nieuwe code weet ik zeker dat ik de herinneringenfunctie zal oppoetsen en deze de komende weken regelmatig zal verbeteren. Doordat Meeting Planner echter is samengevoegd, is vaak meer functionaliteit mogelijk - vaak met weinig werk omdat er een kader en een basis is. Het schone gegevensmodel en MVC-raamwerk maken periodieke verbeteringen relatief eenvoudig.

Dit alles maakt het opbouwen van een startup zowel leuk als uitdagend. En werken met draken (sommige dagen kan ik niet geloven dat ze me betalen om dit te doen).

Wat is het volgende?

Meeting Planner heeft de afgelopen paar maanden enorme vooruitgang geboekt. Ik begin te experimenteren met WeFunder op basis van de implementatie van de nieuwe crowdfundingregels van de SEC. Overweeg om ons profiel te volgen. Ik hoop hierover meer te schrijven in een toekomstige tutorial.

En zeker, de app heeft nog steeds veel tekortkomingen - zorg ervoor dat je je feedback plaatst in de comments of een supportticket opent.

Ik hoop dat je deze aflevering leuk vond. Bekijk de komende tutorials in onze Building Your Startup With PHP-serie - er staat nog steeds Pools werk op de agenda, maar ook meer belangrijke functies.

Aarzel niet om uw vragen en opmerkingen hieronder toe te voegen; Ik neem over het algemeen deel aan de discussies. Je kunt me ook rechtstreeks op Twitter @reifman bereiken.

Gerelateerde Links

  • Meeting Planner
  • Meeting Planner Funding Profile
  • Programmeren met Yii2: Aan de slag
  • De Yii2 Developer Exchange