Dieses Tutorial ist Teil der Reihe Building Your Startup With PHP auf Tuts+. In dieser Serie führe ich Sie durch den Start eines Startups vom Konzept zur Realität anhand meiner Meeting Planner-App als Beispiel aus dem wirklichen Leben. Bei jedem Schritt auf dem Weg veröffentlichen wir den Meeting Planner-Code als Open Source-Beispiele, aus denen Sie lernen können. Wir werden uns auch mit geschäftlichen Problemen im Zusammenhang mit Startups befassen, sobald diese auftreten.
Der gesamte Code für Meeting Planner ist im Yii2 Framework für PHP geschrieben. Wenn Sie mehr über Yii2 erfahren möchten, lesen Sie unsere parallele Serie Programming With Yii2 bei Tuts+. Vielleicht möchten Sie auch auf meiner Knowledge Base-Website nach Yii2-Fragen suchen, The Yii2 Developer Exchange.
In den letzten sechs Tutorials haben wir die Grundlagen für die Anwendungsunterstützung auf verschiedene Weise gelegt: Benutzer, Orte, Kontakte, Einstellungen und Lokalisierung. Ich wette, Sie werden genauso begeistert sein wie ich, dass wir endlich bereit sind, den Zeitplan für eine Besprechungsfunktion zu erstellen. Vielen Dank für Ihre Geduld, da ich die Infrastruktur für die unterhaltsamen, integralen Bestandteile dieser Anwendung aufgebaut habe.
Das Codierungs-Tutorial zur Unterstützung der Zeitplan-Meeting-Funktionalität erstreckt sich jedoch über mindestens vier Episoden. Diese beiden nächsten Episoden konzentrieren sich hauptsächlich darauf, Unterstützung für die grundlegende Benutzererfahrung aufzubauen, den Teilnehmer, den Ort sowie Datum und Uhrzeit für eine Besprechung auszuwählen und diese in der Datenbank zu speichern. Danach kümmern wir uns um die Zustellung der Besprechungsanfrage per E-Mail. Wir werden später in der Serie zurückkehren, um die Benutzeroberfläche zu optimieren und zu verbessern, da dies für den Erfolg dieses Produkts von entscheidender Bedeutung ist. Die Hauptaufgabe für dieses spätere Update besteht darin, Seitenaktualisierungen im Besprechungsplanungsprozess zu vermeiden.
Das Erstellen der Funktionen für dieses Tutorial erforderte eine Menge Code - einige davon wurden automatisch von Yii's Gii generiert und viele von Hand. Aufgrund der Komplexität der Bereitstellung der ersten Teile dieser Funktion habe ich mich auf eine recht rudimentäre Benutzeroberfläche konzentriert, die ich iterativ polieren werde.
Das Erstellen dieser Funktion berührt so viele Aspekte der Programmierung im Yii2-Framework: Active Record-Migrationen, Beziehungen und Validierungen, Gii-Codegenerierung, Bootstrap, Erweiterungen und Widgets der Yii2-JQuery-Benutzeroberfläche, AJAX, Rendern von Teilansichten, DRY-Codierungspraktiken usw. Es war schwierig auszuwählen, was hier behandelt werden sollte. Sie werden viele Änderungen am Repository gegenüber früheren Tutorial-Episoden bemerken.
Wenn Sie Fragen oder Kommentare haben, posten Sie diese bitte unten. Ich nehme an den Diskussionen teil.
Die Meetings-Seite
Bootstrap-Registerkarten
Eines der ersten Dinge, die ich tun muss, ist, verschiedene Registerkarten für zukünftige, vergangene und abgesagte Meetings zu erstellen.
Die Implementierung ist nur ein weiteres Beispiel dafür, wie großartig Bootstrap ist und wie solide die Yii2-Integration mit Bootstrap 3.x ist. Bootstrap verfügt über vorgefertigte Registerkarten.
In MeetingController laden wir Abfragen für jeden Besprechungstyp vor und rendern die Indexansicht:
Wenn wir uns näher mit dieser Serie befassen, werde ich eine Menge Platzhalter für die Arbeit übrig lassen. Eines dieser Dinge ist die Implementierung dieser Registerkarten über AJAX, damit wir nicht drei Abfragen im Voraus laden.
Ticketverfolgung
Ich werde auch damit beginnen, Tickets in der Issue-Tracking-Anwendung Lighthouse für meine zukünftige Arbeit zu erstellen, um die Nachverfolgung zu vereinfachen. Ich werde in einem zukünftigen Tutorial über Lighthouse sprechen.
Was steckt hinter der Planung eines Meetings?
Die einfache Aufgabe, einen Rahmen für die Planung eines Meetings zu erstellen, erwies sich unter der Haube als recht komplex und detailliert. Ich werde dies schrittweise polieren, während wir uns durch die Serie bewegen.
Mein erstes Ziel war es, nur das grundlegende Framework zu erstellen, damit ich die Funktionen der Besprechungsplanung testen kann.
Besprechungen bestehen aus einer Handvoll ActiveRecord-Datenmodellen, z. Teilnehmer, MeetingTime, MeetingPlace, MeetingNote usw. Anfangs wollte ich nur die Yii-Codegenerierung verwenden, um CRUD für jedes dieser Modelle zu erstellen und es dann in eine einzelne Planungsseite zu integrieren.
Die Idee ist, MVC zu verwenden, um all diese Aktionen zu erstellen und dabei so weit wie möglich an der DRY-Methodik festzuhalten. Anfänglich wird die Benutzeroberfläche Seitenaktualisierungen durchführen, aber später werden wir zurückkommen und alle diese Modelle über AJAX mit demselben MVC-Code integrieren.
Das Formular zum Erstellen eines Meetings
Bei vielen Modellen habe ich zunächst den in früheren Tutorials beschriebenen Prozess zur Verwendung von Yii-Codegenerator Gii zum Erstellen von CRUD durchlaufen. Dann habe ich sie nach Bedarf angepasst. Im Moment bleibe ich bei einem sehr einfachen Formular zum Erstellen eines Meetings - es enthält noch nicht einmal die E-Mail-Adresse des Teilnehmers. Auf diese Weise kann ich schnell einen grundlegenden Besprechungsdatensatz erstellen und an der Planungsseite arbeiten.
Sobald das Formular gesendet wurde, können Sie die Besprechungsseite anzeigen. Natürlich werde ich dieses Formular und den ersten Prozess rechtzeitig ändern.
Die Besprechungsseite
Erinnern Sie sich an mein Modell für das erste Tutorial in dieser Reihe:
Hier ist eine frühe Darstellung der Form, in der ich arbeite:
Es gibt eine Menge Infrastruktur, Code (sowohl automatisch generiert als auch manuell generiert) und Widgets von Drittanbietern, die dafür verantwortlich sind. Ich werde dich Stück für Stück durch das Buch führen.
Bootstrap-Panels und -Tabellen
Obwohl dies wahrscheinlich nicht das endgültige Design ist, habe ich mich für die Verwendung von Bootstrap-Bedienfeldern entschieden, um die Seite zwischen Eigenschaften, Orten, Datums- und Uhrzeitangaben sowie Notizen zu organisieren. Die Seite selbst wird durch die Aktion View des Besprechungscontrollers gerendert und ruft für jedes dieser Elemente Teilansichten zu den jeweiligen Modellen auf.
Ich musste es nicht so erstellen, aber ich wollte absichtlich das gesamte integrierte MVC-Framework von Yii nutzen und die Dinge so weit wie möglich integrieren. Ich hatte die Hoffnung, dass es in Zukunft einfacher sein wird, die gesamte Seite zu AJAXifizieren, Seitenaktualisierungen zu reduzieren und die Einfachheit und Wartbarkeit des Quellcodes zu erhöhen.
So funktioniert die Aktion View Meeting-Controller. Es lädt ActiveDataProviders für jedes der Modelle und rendert dann die Besprechungsansichtsdatei:
Durch die Verwendung aller Ansichten in jedem der zugeordneten Modelle ist es ziemlich einfach, die gesamte Zeitplanseite mit MVC-Teilansichten anzuzeigen. In der Besprechungsansicht werden alle _panel-Ansichten für die anderen Modelle gerendert. Hier können Sie die Dokumentation zur Rendermethode von Yii2 einsehen.
1
<?=$this->render('../participant/_panel',[
2
'model'=>$model,
3
'participantProvider'=>$participantProvider,
4
])?>
5
6
<?=$this->render('../meeting-place/_panel',[
7
'model'=>$model,
8
'placeProvider'=>$placeProvider,
9
])?>
10
11
<?=$this->render('../meeting-time/_panel',[
12
'model'=>$model,
13
'timeProvider'=>$timeProvider,
14
])?>
15
16
<?=$this->render('../meeting-note/_panel',[
17
'model'=>$model,
18
'noteProvider'=>$noteProvider,
19
])?>
Fehlende Modelle
Beim Erstellen dieser Funktionalität wurde mir klar, dass ich einige notwendige Modelle vernachlässigt hatte: MeetingPlaceChoice und MeetingTimeChoice. Diese sind erforderlich, um die Verfügbarkeit des Veranstalters und der Teilnehmer für bestimmte MeetingPlaces und MeetingTimes zu speichern.
Hier ist die Migration für MeetingPlaceChoice:
1
$this->createTable('{{%meeting_place_choice}}',[
2
'id'=>Schema::TYPE_PK,
3
'meeting_place_id'=>Schema::TYPE_INTEGER.' NOT NULL',
4
'user_id'=>Schema::TYPE_BIGINT.' NOT NULL',
5
'status'=>Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0',
Mit den ActiveRecord-Migrationen von Yii können Sie Ihr Datenbankschema im Verlauf Ihres Produkts auf einfache Weise programmgesteuert erweitern.
Diese Modelle bestimmen den Status der Switch-Widgets (die die Verfügbarkeit der Benutzer widerspiegeln), die Sie oben in den Zeilen für jeden Ort und jede Uhrzeit sehen. Im folgenden Tutorial werde ich Ihnen zeigen, wie wir diese Widgets initialisieren und AJAX in Yii verwenden, um ihren Status ohne Seitenaktualisierung zu aktualisieren.
Planen von Warnungen
Die PrepareView ermittelt den Status der Besprechung und warnt den Benutzer bei Bedarf, dass die Einladung nicht gesendet wurde:
1
publicfunctionprepareView(){
2
$this->setViewer();
3
$this->canSend();
4
$this->canFinalize();
5
// has invitation been sent
6
if($this->canSend()){
7
Yii::$app->session->setFlash('warning',Yii::t('frontend','This invitation has not yet been sent.'));
8
}
9
// to do - if sent, has invitation been opened
10
// to do - if not finalized, is it within 72 hrs, 48 hrs
11
}
Yii verfügt über eine integrierte Unterstützung für die Anzeige von Bootstrap-Warnungen, die als Flashes bezeichnet werden:
Befehlsschaltflächen
Hier ist der Code für einen Beispielcontainer für Besprechungsansichten mit den oben gezeigten Befehlsschaltflächen:
Für die Schaltflächen zum Abbrechen und Bearbeiten von Eigenschaften habe ich Glyphicons verwendet. Glyphicons sind wunderschön und frei in Bootstrap enthalten und in Yii2 integriert.
Was machen diese Befehle?
Sobald der Benutzer einen Teilnehmer und mindestens einen Ort sowie Datum und Uhrzeit hinzugefügt hat, kann er die Einladung senden. Diese Funktion sendet dem Benutzer eine Besprechungseinladung per E-Mail, die ich in Kürze in einem Tutorial beschreiben werde.
Über die Schaltfläche Finalisieren kann der Organisator (oder Teilnehmer) den Status des Meetings von "Planung" auf "Bevorstehend" ändern. Die Idee ist, dass nach Auswahl eines Ortes und einer Uhrzeit das Meeting "abgeschlossen" werden kann. Zuvor hat der Teilnehmer die Möglichkeit, optional andere Orte und Datumsangaben vorzuschlagen, und der Veranstalter (oder beide) hat die Möglichkeit, den endgültigen Ort und die Datums- und Uhrzeitangabe auszuwählen.
Mit der Schaltfläche Abbrechen wird die Besprechung abgebrochen und auf die Registerkarte Abgebrochen auf der Seite Besprechungen verschoben.
Teilnehmer
Als nächstes fügt der Benutzer Personen hinzu.
Hinweis: In meinem Produkt mit minimaler Lebensfähigkeit ist nur ein Teilnehmer zulässig, wir können jedoch später weitere hinzufügen.
Wenn Sie sich an die Freundes-Tabelle erinnern, die wir in einem früheren Lernprogramm erstellt haben, können Benutzer eine neue E-Mail-Adresse eingeben oder ihre Eingabe beschleunigen, indem die automatische Vervollständigung aus ihren vorhandenen Freunden und früheren Besprechungen geladen wird.
In Zukunft werden wir hier mehr Optionen für die Benutzeroberfläche haben - einschließlich häufiger Teilnehmer.
Hier ist die _form.php in \frontend\views\participant:
1
<divclass="participant-form">
2
<?php$form=ActiveForm::begin();?>
3
4
<?=$form->errorSummary($model);?>
5
6
<p>Email address:</p>
7
<?php
8
// preload friends into array
9
echoyii\jui\AutoComplete::widget([
10
'model'=>$model,
11
'attribute'=>'email',
12
'clientOptions'=>[
13
'source'=>$friends,
14
],
15
]);
16
?>
Ich habe die Entwurfsentscheidung getroffen, alle Teilnehmer in der Benutzertabelle zu speichern. Ich kann das bereuen - noch nicht sicher. Dies vereinfacht jedoch den Prozess, die es den Nutzern ermöglicht, die Site schnell zu nutzen, erheblich und vereinfacht das gesamte Datenmodell.
Wenn ein Benutzer jemanden einlädt, der dem System unbekannt ist (eine neue E-Mail-Adresse), registrieren wir ihn passiv in der Benutzertabelle.
Wir erstellen einen Benutzernamen basierend auf ihrer E-Mail-Adresse. Ich benutze Yiis Schneckengenerator in seinem Inflector-Helfer. Wir erstellen vorerst ein zufälliges Passwort mit dem Sicherheitshelfer von Yii. Wenn ich Vanilla PHP verwenden würde, müsste ich wahrscheinlich andere Funktionen für diese Funktionen integrieren. Stattdessen ist es direkt eingebaut.
Fahren wir mit dem Hinzufügen von Orten fort.
Setzt
Die Verwendung der MVC von Yii für jeden Controller und jedes Modell bietet große Vorteile, anstatt all diese Funktionen in den Meeting-Controller zu codieren. Dies macht das Verstehen und Verwalten des Codes viel einfacher und übersichtlicher.
Ich bemerkte jedoch schnell, dass ich die Standard-Breadcrumbs anpassen musste, um auf die aktuelle Besprechungsseite und nicht auf den Index oder die Ansicht für ein bestimmtes Modell zurückzugreifen.
Wir verwenden das MeetingPlace-Modell, um Besprechungen Orte hinzuzufügen. In \frontend\views\meet-place\create.php musste ich einfach die Links im breadcrumbs-Bereich anpassen:
1
<?php
2
3
useyii\helpers\Html;
4
5
/* @var $this yii\web\View */
6
/* @var $model frontend\models\MeetingPlace */
7
8
$this->title=Yii::t('frontend','Add a {modelClass}',[
Unterstützung für das direkte Hinzufügen von Google Places hinzufügen
Ich wollte nicht nur das Formular zur Ortserstellung anpassen, damit der Benutzer zuvor verwendete Orte hinzufügen kann, sondern auch, um neue Google Places im laufenden Betrieb hinzuzufügen.
Grundsätzlich musste ich die Unterstützung, die wir im Google Places-Tutorial hier in der MeetingPlace-Erstellung erstellt haben, replizieren:
1
<?php
2
useyii\helpers\ArrayHelper;
3
useyii\helpers\BaseHtml;
4
useyii\helpers\Html;
5
useyii\widgets\ActiveForm;
6
usefrontend\models\UserPlace;
7
8
usefrontend\assets\MapAsset;
9
MapAsset::register($this);
10
11
/* @var $this yii\web\View */
12
/* @var $model frontend\models\MeetingPlace */
13
/* @var $form yii\widgets\ActiveForm */
14
?>
15
16
<divclass="meeting-place-form">
17
18
<?php$form=ActiveForm::begin();?>
19
20
<?=$form->errorSummary($model);?>
21
22
<h3>Choose one of your places</h3>
23
<divclass="row">
24
<divclass="col-md-6">
25
<?=Html::activeDropDownList($model,'place_id',
26
ArrayHelper::map(UserPlace::find()->all(),'place.id','place.name'),['prompt'=>Yii::t('frontend','-- select one of your places below --')])?>
27
<h3>- or -</h3>
28
<h3>Choose from Google Places</h3>
29
<p>Type in a place or business known to Google Places:</p>
Ich musste auch die ausgefeilte Validierungsunterstützung von Yii2 stärker nutzen. Im folgenden MeetingPlace-Modell verwenden wir die eindeutige Validierung von Yii2, um einen Fehler zu melden, wenn jemand versucht, einen bereits vorgeschlagenen Ort für ein Meeting zu finden:
[['place_id'],'unique','targetAttribute'=>['place_id','meeting_id'],'message'=>Yii::t('frontend','This place has already been suggested.')],
Ich habe außerdem eine benutzerdefinierte Fehlerbedingung in der MeetingPlaceController-Erstellungsaktion hinzugefügt, wenn ein Nutzer Orte aus seiner Liste sowie Google Place auswählt - obwohl dies möglicherweise eine optionale Funktion ist, die beibehalten werden soll (haben Sie eine Meinung? Beitrag in den Kommentaren unten):
Ich habe auch einen Fehler aus Episode drei behoben, bei dem mehrere Kartenfelder erstellt wurden, wenn jemand die Google Place-Auswahl änderte. Die Überprüfung der Anzahl der in der article-Auswahl vorhandenen Kinder hat Folgendes behoben:
In Zukunft wird dieses Erstellungsformular eine Reihe wichtiger Funktionen enthalten:
Ermöglichen Sie Benutzern, ihre aktuelle Geolokalisierung hinzuzufügen.
Schlagen Sie vom Benutzer vorgeschlagene häufige Orte vor.
Bieten Sie schnellen Zugriff auf die Lieblingsorte des Benutzers.
Schlagen Sie Orte in der Nähe (in gleichem Abstand) des Benutzers und der Teilnehmer vor.
Schlagen Sie gesponserte Plätze von bezahlten Werbetreibenden vor.
Ermöglichen, dass Orte und Datums- und Uhrzeitangaben vom Veranstalter entfernt werden - möglicherweise unter der Bedingung, dass sie von den Teilnehmern nicht gesehen oder beantwortet wurden.
Es kann auch nützlich sein, Benutzern das Notieren bestimmter Orte und Datumszeiten zu ermöglichen. Zum Beispiel könnte ich bezeichnen, dass "dieser Ort am Donnerstagmorgen gut für mich funktioniert, aber nicht am Freitagnachmittag" oder "wenn Sie diesmal wählen, können wir es im Caffe Vita auf dem Capitol Hill tun". Wenn Sie eine Meinung zu dieser Funktion haben (was die Komplexität erhöhen würde), geben Sie unten einen Kommentar ab.
Anzeigen der Panels
Für jedes Modell verwenden wir eine ähnliche Hierarchie von Ansichten und Yii2-Komponenten. Der Meeting Controller rendert die Ansicht für _panel.php in \frontend\views\meeting-place:
Der Umriss der Bootstrap-kompatiblen Tabelle befindet sich in _panel.php. Anschließend verwenden wir das Widget Yii2 Listview, um jede Datenzeile in Tabellenform anzuzeigen. Der itemView-Teil befindet sich in _list.php.
Beachten Sie, dass wir eine benutzerdefinierte Variable namens placeCount über viewParams übergeben. Dies ist praktisch zum Konfigurieren der Schaltflächen in der Tabelle.
Hier ist die Ansicht _list.php, die ich im nächsten Tutorial ausführlicher behandeln werde, einschließlich der Widgets für die Schaltereingabe und der AJAX-Implementierung.
Es gibt einige Verbesserungen, die ich in Zukunft an diesem Widget vornehmen möchte. Ich möchte es beim Laden automatisch öffnen, für das es derzeit keine Einstellung zu geben scheint.
Auch hier verwenden wir den eindeutigen Validator, um sicherzustellen, dass das bestimmte Datum und die Uhrzeit noch nicht zum Meeting hinzugefügt wurden:
Mithilfe von Besprechungsnotizen können Benutzer nach Belieben kommunizieren und Orte und Datums- und Uhrzeitangaben auswählen, ohne sich gegenseitig separat per E-Mail benachrichtigen zu müssen.
So sehen Notizen auf der Besprechungsseite aus:
Die Implementierung von Notizen ist nahezu identisch mit der obigen Implementierung von Orten und Datumsangaben. Weitere Informationen finden Sie in den Dateien MeetingNote-Controller und \frontend\views\meeting-note-Ansicht.
Was kommt als nächstes?
Ich hoffe, Sie haben mit diesem Tutorial etwas Neues gelernt. Achten Sie auf kommende Tutorials in meiner Reihe Erstellen Sie Ihr Startup mit PHP - es stehen viele unterhaltsame Funktionen an.
Im nächsten Tutorial werde ich mich eingehend mit der Implementierung der Optionen für Ort und Datum und Uhrzeit mit AJAX befassen. Danach beginnen wir mit dem Erstellen von E-Mail-Nachrichten, um die Nachrichteneinladungen zuzustellen, die Antworten der Teilnehmer auf der Zeitplanseite zu sammeln und Besprechungen für die reale Welt abzuschließen.
Bitte zögern Sie nicht, Ihre Fragen und Kommentare unten hinzuzufügen; Ich nehme in der Regel an den Diskussionen teil. Sie können mich auch auf Twitter @reifman erreichen oder mir direkt eine E-Mail senden.
Jeff Reifman is a experienced technology consultant, former Microsoft Group Program Manager, writer, activist and yogi. He's the founder of Meeting Planner and author of the Envato Tuts+ series, Building Your Startup. He enjoys travel, photography and snowboarding in his free time.