Programmieren mit Yii2 Schuldiges Verhalten

Was Sie erstellen werden

Wenn Sie fragen: "Was ist Yii?" Schauen Sie sich mein früheres Tutorial an: Einführung in das Yii-Framework, Hier werden die Vorteile von Yii beschrieben und ein Überblick über die Neuerungen in Yii 2.0 (Oktober 2014) gegeben.

In dieser Programmierserie mit Yii2 leite ich die Leser beim Einsatz des neu aktualisierten Yii2-Frameworks für PHP. In diesem Lernprogramm führe ich Sie durch ein anderes interessantes Verhalten von Yii2: Automatisieren Sie die allgemeine Webentwicklungsaufgabe, die von user_ids erstellt und von allen Modellen in Ihrer Web-App mithilfe von DRY-Codierung und Yii2 BlameableBehavior aktualisiert wird. Wir erstellen auch ein Protokoll, in dem aufgezeichnet wird, wer die Statustabelle für jede vorgenommene Änderung aktualisiert hat.

Für diese Beispiele stellen wir uns weiterhin vor, dass wir ein Framework für die Veröffentlichung einfacher Statusaktualisierungen erstellen, z. unser eigenes Mini-Twitter.

Nur zur Erinnerung, ich beteilige mich an den Kommentarthreads unten. Ich bin besonders interessiert, wenn Sie unterschiedliche Ansätze, zusätzliche Ideen haben oder Themen für zukünftige Tutorials vorschlagen möchten.

Was ist ein Verhalten??

Yii2 Verhalten sind im Wesentlichen Mixins. Wikipedia beschreibt Mixins als "eine Klasse, die eine Kombination von Methoden aus anderen Klassen enthält. Wie eine solche Kombination durchgeführt wird, hängt von der Sprache ab, jedoch nicht von Vererbung."

Yii beschreibt sie so:

Durch das Anhängen eines Verhaltens an eine Komponente werden die Methoden und Eigenschaften des Verhaltens in die Komponente eingefügt, wodurch diese Methoden und Eigenschaften so zugänglich gemacht werden, als wären sie in der Komponentenklasse selbst definiert.

Yii2 bietet mehrere integrierte Verhaltensweisen, von denen die meisten dokumentiert werden, darunter träge (siehe Programmieren mit Yii2: trollbares Verhalten), fehlerhaftes Verhalten und Zeitstempel (in Kürze siehe Seite der Serie). Verhalten sind eine einfache Möglichkeit, allgemeinen Code in vielen Ihrer Datenmodelle wiederzuverwenden, ohne den Code an vielen Stellen wiederholen zu müssen. Das Einfügen eines Verhaltens in ein Modell kann oft mit nur zwei Codezeilen erfolgen. Mit zunehmender Anzahl von Modellen in Ihrer Anwendung werden Verhaltensweisen immer nützlicher.

Was ist das schuldige Verhalten?

Blameable macht es uns leicht, die häufig benötigte Aufgabe zu implementieren, den aktuell angemeldeten Benutzer Einfügungen und Aktualisierungen in einem ActiveRecord-Modell zuzuordnen, wobei die Eigenschaften für automatisch festgelegt werden erstellt von und aktualisiert von.

In der Programmierung mit Yii2: Autorisierung Mit dem Access Control Filter haben wir unser eigenes schuldhaftes Verhalten in zwei Teilen implementiert. Zuerst haben wir eine Migration erstellt, um a hinzuzufügen erstellt von Feld zu unserer Statustabelle:

db-> driverName === 'mysql') $ tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> addColumn ('% status', 'created_by', Schema :: TYPE_INTEGER. 'NOT NULL'); $ this-> addForeignKey ('fk_status_created_by', '% status', 'created_by', '% user', 'id', 'CASCADE', 'CASCADE'); 

Zweitens haben wir die zugewiesen erstellt von Feld zum aktuellen Benutzeridentifikation in der Create-Aktion des StatusControllers:

öffentliche Funktion actionCreate () $ model = new Status (); if ($ model-> load (Yii :: $ app-> request-> post ())) $ model-> created_by = Yii :: $ app-> user-> getId ();

Das Implementieren des Blameable-Verhaltens erledigt dies automatisch für uns und kann problemlos zu allen ActiveRecord-Modellen in einer Webanwendung hinzugefügt werden.

Implementieren des blameable-Verhaltens im Statusmodell

Statustabelle erweitern

Erstens müssen wir die Statustabelle noch einmal um eine Migration erweitern, um eine zu unterstützen aktualisiert von Feld.

Jeff $ ./yii migrieren / erstellen extend_status_table_for_updated_by Yii Migration Tool (basierend auf Yii v2.0.2) Neue Migration erstellen '/Users/Jeff/Sites/hello/migrations/m150209_200619_extend_status_table_for_updated_by.php'? (ja | nein) [nein]: ja Die neue Migration wurde erfolgreich erstellt.

Hier ist der Migrationscode, den wir verwenden werden:

db-> driverName === 'mysql') $ tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> addColumn ('% status', 'updated_by', Schema :: TYPE_INTEGER. 'NOT NULL'); $ this-> addForeignKey ('fk_status_updated_by', '% status', 'updated_by', '% user', 'id', 'CASCADE', 'CASCADE');  public function down () $ this-> dropForeignKey ('fk_status_updated_by', '% status'); $ this-> dropColumn ('% status', 'updated_by');  

Wenn Sie versuchen, diese Migration mit vorhandenen Daten in Ihrer Datenbank auszuführen, erhalten Sie eine Fehlermeldung, wenn Sie versuchen, den Fremdschlüsselindex zu erstellen aktualisiert von ist 0 und ist in der Benutzertabelle nicht vorhanden. 

Hallo Jeff $ ./yii migrate / up Yii Migration Tool (basierend auf Yii v2.0.2) Insgesamt 1 neu anzuwendende Migration: m150209_200619_extend_status_table_for_updated_by Übernehmen Sie die obige Migration? (Ja | Nein) [Nein]: Ja *** m150209_200619_extend_status_table_for_updated_by anwenden> Spalte aktualisiert_von Ganzzahl NOT NULL zu Tabelle % status hinzufügen ... done (Zeit: 0.042s)> Fremdschlüssel hinzufügen fk_status_updated_by: % status (updated_by) verweist auf % user (id)… Ausnahme 'yii \ db \ IntegrityException' mit der Nachricht 'SQLSTATE [23000]: Verletzung der Integritätsbedingung: 1452 Eine untergeordnete Zeile kann nicht hinzugefügt oder aktualisiert werden: Eine Fremdschlüsseleinschränkung schlägt fehl (' Hallo '.' # sql-22f_1d0 ', CONSTRAINT' fk_status_updated_by 'FOREIGN KEY (' updated_by ') REFERENCES' user '(' id ') ON DELETE CASCADE AUF UPDATE CASCADE) Die ausgeführte SQL war: ALTER TABLE' status 'ADD CONSTRAINT 'fk_status_updated_by' FOREIGN KEY ('updated_by') VERWEISE 'user' ('id') ON DELETE CASCADE ON UPDATE CASCADE 'in /Users/Jeff/Sites/hello/vendor/yiisoft/yiiisoft/yii2/db/Schema.php:532 Fehler Info: Array ([0] => 23000 [1] => 1452 [2] => Eine untergeordnete Zeile kann nicht hinzugefügt oder aktualisiert werden: Eine Fremdschlüsseleinschränkung schlägt fehl ('Hallo'. '# Sql-22f_1d0', CONSTRAINT 'fk_status_updated_by' VORDERGRUND IGN-TASTE ('updated_by') REFERENCES 'user' ('id') ON DELETE CASCADE ON UPDATE CASCADE)) 

Sie können dies umgehen, indem Sie die Daten in der Migration manuell aktualisieren und dann einen Fremdschlüssel hinzufügen. Da dies jedoch eine Testplattform ist, ist es am einfachsten, nur drei Schritte hinab zu migrieren, wobei die Statustabelle und ihre Testdaten gelöscht werden, und dann erneut zu migrieren:

hallo Jeff $ ./yii migrieren / down 3 Yii Migration Tool (basierend auf Yii v2.0.2) Insgesamt 3 Migrationen, die rückgängig gemacht werden sollen: (Ja | Nein) [Nein]: Ja *** Zurücksetzen von m150128_233458_extend_status_table_for_slugs> Lösche den Spalten-Slug aus der Tabelle % status… erledigt (Zeit: 0,009s) *** Umgekehrt: m150128_233458_extend_status_table_for_slugs (Zeit: 0,013s) m150128_003709_extend_status_table_for_created_by> Entfernt den Fremdschlüssel fk_status_created_by aus der Tabelle % status… done (Zeit: 0.010s)> löscht die Spalte create_by aus der Tabelle % status… erledigt (Zeit: 0.008s) *** reverted 0.019s) *** Umkehrung von m141201_013120_create_status_table> Drop-Tabelle % status… fertig (Zeit: 0,001s) *** Umkehrung von m141201_013120_create_status_table (Zeit: 0,002s) Die Migration wurde erfolgreich abgebrochen. Hallo Jeff $ ./yii migrieren / bis 4 Yü Migration Tool (basierend auf Yü v2.0.2) Insgesamt 4 neue Migrationen anzuwenden: m141201_013120_create_status_table m150128_003709_extend_status_table_for_created_by m150128_233458_extend_status_table_for_slugs m150209_200619_extend_status_table_for_updated_by die oben Migrationen anwenden? (Ja | Nein) [Nein]: Ja *** Anwenden von m141201_013120_create_status_table> Tabelle erstellen % status… done (Zeit: 0,007s) *** angewendet Anwenden von m141201_013120_create_status_table (Zeit: 0.010s) *** Anwenden von m150128_003709_extend_status_tool_contact Spalte created_by integer NOT NULL für Tabelle % status ... done (Zeit: 0,007 s)> Fremdschlüssel hinzufügen fk_status_created_by: % status (Created_by) verweist auf % user (id)… done (Zeit) : 0.008s) *** angewendet m150128_003709_extend_status_table_for_created_by (Zeit: 0.016s) *** Anwenden von m150128_233458_extend_status_table_for_slugs> Fügen Sie der Tabelle % status einen Spalten-Slug-String NOT NULL hinzu… : 0.008s) *** Anwenden von m150209_200619_extend_status_table_for_updated_by> Hinzufügen der Spalte aktualisiert_von der Ganzzahl NOT NULL zur Tabelle % status… fertig (Zeit: 0,007 s)> Hinzufügen des Fremdschlüssels fk_status_updated_by: status (updated_by) referenzen  % user (id)… fertig (Zeit: 0,007s) *** angewendet m 150209_200619_extend_status_table_for_updated_by (Zeit: 0.015 Sekunden) Erfolgreich migriert.

Hinzufügen des BlameableBehavior zum Statusmodell

Als Nächstes hängen wir das BlameableBehavior an unser Statusmodell an. In models / Status.php fügen wir das BlameableBehavior nach Sluggable hinzu:

Klasse Status erweitert \ yii \ db \ ActiveRecord const PERMISSIONS_PRIVATE = 10; const PERMISSIONS_PUBLIC = 20; public function behaviors () return [['class' => SluggableBehavior :: className (), 'attribut' => 'message', 'immutable' => true, 'sureUnique' => true,], ['class' => BlameableBehavior :: className (), 'createdByAttribute' => 'created_by', 'updatedByAttribute' => 'updated_by',],]; 

Das blameable-Verhalten muss an der Spitze unseres Modells enthalten sein:

Dann entfernen wir die erforderliche Regel für erstellt von in den Modellregeln:

Regeln für öffentliche Funktionen () return [[['' message ',' created_at ',' updated_at ',' created_by '],' required '],

So was:

Regeln für öffentliche Funktionen () return [[[['' message ',' created_at ',' updated_at '],' required '],

Dadurch kann die Validierung erfolgreich sein und mit den Verhaltensweisen fortfahren.

Wir können die StatusController auch auskommentieren oder löschen erstellt von Zuordnung in der Erstellungsaktion:

öffentliche Funktion actionCreate () $ model = new Status (); if ($ model-> load (Yii :: $ app-> request-> post ())) // $ model-> created_by = Yii :: $ app-> user-> getId ();

Sobald alle diese Änderungen abgeschlossen sind, können wir einen neuen Statusbeitrag schreiben:

Mit PHPMyAdmin können wir einen Blick in die Tabellensicht werfen und die Einstellungen created_by und updated_by sehen:

Protokollierung von Aktualisierungen der Statustabelle

Wenn ein Status-Beitrag erstellt wird, wissen wir immer, wer den ersten Eintrag erstellt hat. Mit blameable Behaviours wissen wir jedoch nur, wer den Datensatz zuletzt aktualisiert hat.

Gehen wir durch eine einfache Protokollimplementierung, um die ID der Person aufzuzeichnen, die jedes Update vornimmt. Dann können Sie leicht einen Verlauf der Aktualisierungsprogramme anzeigen oder dieses zu einem vollständigen Revisionsprotokoll erweitern.

Erstellen der Tabelle für StatusLog

Zuerst müssen wir eine Migration für die erstellen StatusLog:

Hallo Jeff $ ./yii migrieren / erstellen create_status_log_table Yii Migration Tool (basierend auf Yii v2.0.2) Neue Migration erstellen '/Users/Jeff/Sites/hello/migrations/m150209_204852_create_status_log_table.php'? (ja | nein) [nein]: ja Die neue Migration wurde erfolgreich erstellt.

Anschließend kodieren wir die Migration, um relationale Felder für die Statustabellen-ID und den Benutzer aufzunehmen aktualisiert von Felder:

db-> driverName === 'mysql') $ tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> createTable ('% status_log', ['id' => Schema :: TYPE_PK, 'status_id' => Schema :: TYPE_INTEGER. 'NOT NULL', 'updated_by' => Schema :: TYPE_INTEGER. 'NOT NULL', 'created_at' => Schema :: TYPE_INTEGER. 'NOT NULL',], $ tableOptions); $ this-> addForeignKey ('fk_status_log_id', '% status_log', 'status_id', '% status', 'id', 'CASCADE', 'CASCADE'); $ this-> addForeignKey ('fk_status_log_updated_by', '% status_log', 'updated_by', '% user', 'id', 'CASCADE', 'CASCADE');  public function down () $ this-> dropForeignKey ('fk_status_updated_by', '% status_log'); $ this-> dropForeignKey ('fk_status_id', '% status_log'); $ this-> dropColumn ('% status_log', 'updated_by');  

Als Nächstes führen wir die Migration aus:

Hallo Jeff $ ./yii migrate / up Yii Migration Tool (basierend auf Yii v2.0.2) Insgesamt 1 neu anzuwendende Migration: m150209_204852_create_status_log_table Anwenden der obigen Migration? (Ja | Nein) [Nein]: Ja *** Anwenden von m150209_204852_create_status_log_table> Tabelle % status_log erstellen ... (Zeit: 0,008 s)> Fremdschlüssel hinzufügen fk_status_log_id: % status_log (status_id) referenzen  % status (id)… done (Zeit: 0,008s)> Fremdschlüssel hinzufügen fk_status_log_updated_by: % status_log (updated_by) verweist auf % user (id)… fertig (Zeit: 0,008s) ** * angewendet m150209_204852_create_status_log_table (Zeit: 0,028 Sekunden) Erfolgreich migriert.

Der schnellste Weg, um ein Modell für StatusLog (und CRUD-Dateien, damit wir die Tabelle problemlos durchsuchen können) zu erstellen, ist der Yii2-Code-Generator Gii. Sie haben gesehen, wie ich es in früheren Tutorials verwendet habe.

Besuchen Sie http: // localhost: 8888 / hello / gii und erstellen Sie das Modell mit diesen Einstellungen:

Hier sind die CRUD-Einstellungen:

Als Nächstes erweitern wir das AfterSave-Ereignis im Statusmodell:

öffentliche Funktion afterSave ($ insert, $ changedAttributes) parent :: afterSave ($ insert, $ changedAttributes); // Wenn insert false ist, wurde der Datensatz aktualisiert if (! $ insert) // StatusLog-Eintrag hinzufügen $ status_log = new StatusLog; $ status_log-> status_id = $ this-> id; $ status_log-> updated_by = $ this-> updated_by; $ status_log-> created_at = time (); $ status_log-> save (); 

Diese Methode ruft die übergeordnete Standardfunktion für auf afterSave erstellt dann jedoch einen neuen StatusLog-Eintrag, wenn eine Statuszeile aktualisiert wird:

Theoretisch könnten wir auch BlameableBehavior erweitern. Da Sie jedoch sicherstellen müssen, dass für jedes ActiveRecord-Modell, mit dem Sie es verwenden, ein Protokollmodell vorhanden ist, schien es einfacher, diese Funktionalität in Status zu integrieren.

Wenn Sie einige Statussätze aktualisieren, können Sie das StatusLog mit Gii's CRUD durchsuchen. Das Bild unten zeigt zwei Änderungen, die von Status.id 1 vorgenommen wurden.

Wenn Sie weiter gehen möchten, sollte es relativ unkompliziert sein, diese auf eine Revisionstabelle mit vorherigem und neuem Statustext zu erweitern, um die Rollback-Funktion zu unterstützen.

Was kommt als nächstes?

Ich hoffe, es hat Ihnen Spaß gemacht, etwas über Yii2 Behaviours und Blameable zu lernen. Als Nächstes untersuchen wir das Verhalten von Zeitstempeln. Dadurch wird die Menge an Code reduziert, die Sie mit jedem neuen Modell schreiben müssen, um Zeitstempel für Einfügungen und Aktualisierungen zu erstellen.

Achten Sie auf kommende Tutorials in meiner Programmierreihe "Programmieren mit Yii2", während ich mich weiter mit verschiedenen Aspekten des Frameworks beschäftige. Vielleicht möchten Sie auch meine Erstellung Ihres Startups mit der PHP-Serie überprüfen, die die erweiterte Vorlage von Yii2 verwendet, während ich eine reale Weltanwendung baue.

Ich freue mich über Feature- und Themenanfragen. Sie können sie in den Kommentaren unten posten oder mich auf meiner Lookahead Consulting-Website per E-Mail benachrichtigen.

Wenn Sie wissen möchten, wann das nächste Yii2-Tutorial ankommt, folgen Sie mir @reifman auf Twitter oder besuchen Sie meine Instructor-Seite. Meine Ausbilderseite enthält alle Artikel dieser Serie, sobald sie veröffentlicht sind. 

ähnliche Links

  • Der endgültige Leitfaden für Yii2: Verhalten
  • Yii2-Dokumentation: Schuldiges Verhalten
  • Yii2 Developer Exchange, meine eigene Yii2-Ressourcenseite