2015-01-27 1 views
7

Ich habe ein Problem mit Yii2 beim Hinzufügen von TimestampBehavior zur Ausführung aus der Hauptkonfiguration. Der Grund ist, dass ich es bei den meisten meiner Modelle im Frontend und Backend verwenden muss.Anfügen von Verhalten global für alle Modelle in der Anwendungskonfiguration (ohne Vererbung)

Um es in einem Modell ist einfach:

public function behaviors() 
{ 
    return [ 
     [ 
      'class' => TimestampBehavior::className(), 
      'createdAtAttribute' => 'created_at', 
      'updatedAtAttribute' => 'updated_at', 
      'value' => function(){ return date('Y-m-d H:i:s'); } , 
     ], 
    ]; 
} 

Aber wenn ich versuche, das Verhalten in main.php passiert nichts hinzuzufügen. Ich dachte an:

'as timestamp'=>[ 
    'class'=> \yii\behaviors\TimestampBehavior::className(), 
    'createdAtAttribute' => 'created_at', 
    'updatedAtAttribute' => 'updated_at', 
    'value' => function(){ return date('Y-m-d H:i:s'); } , 
], 

Aber es funktioniert nicht. Irgendwelche Ideen?

+0

Ist es im Wesentlichen für Sie es in Config tun? – arogachev

+0

Ich kann es überall sonst machen, aber ich sehe nicht wo. Ich möchte kein Modell mit dem Verhalten machen, und dann alle Modelle von diesem erweitern – cku2014

+3

@ cku2014 Warum nicht? Es ist der richtige Weg, es zu tun. – Masiorama

Antwort

10

Wenn Sie keine Vererbung verwenden möchten, kann ich die folgende Methode vorschlagen.

Der Grundgedanke dahinter ist mit Ereignissen von ActiveRecord:

use yii\base\Event; 
use yii\behaviors\TimestampBehavior; 
use yii\db\ActiveRecord; 

... 

$events = [ActiveRecord::EVENT_BEFORE_INSERT, ActiveRecord::EVENT_BEFORE_UPDATE]; 

foreach ($events as $eventName) { 
    Event::on(ActiveRecord::className(), $eventName, function ($event) { 
     $model = $event->sender; 

     if ($model->hasAttribute('created_at') && $model->hasAttribute('updated_at')) { 
      $model->attachBehavior('timestamp', [ 
       'class' => TimestampBehavior::className(), 
       'value' => function() { 
        return date('Y-m-d H:i:s'); 
       }, 
      ]); 
     } 
    }); 
} 

Dieser Code dynamisch TimestampBehavior für alle Modelle anbringt, die von yii\db\ActiveRecord, bevor sie in die Datenbank übernommen werden zu speichern.

Sie können createdAtAttribute und updatedAtAttribute auch weglassen, weil sie bereits standardmäßig diese Namen haben (da es am häufigsten vorkommt).

Wie Sie sehen können, ist das Verhalten nur angefügt, wenn die Attribute created_at und updated_at vorhanden sind, es ist nicht notwendig, ein erweitertes Verhalten dafür zu erstellen.

Um Vererbung und Kopieren/Einfügen zu vermeiden, sollte dieser Code auf jedem Anwendungs-Bootstrap ausgeführt werden.

Sie können dies zum Eingabeskript (vor dem Ausführen der Anwendung) sofort hinzufügen und es wird funktionieren, aber es ist nicht ratsam, es hier zu platzieren, auch diese Dateien werden automatisch generiert und in git ignorierte Dateiliste.

Sie müssen also nur eine separate Komponente erstellen, die diese Logik enthält und sie in die Konfiguration aufnehmen. Keine Notwendigkeit, Klassen usw. zu erweitern.

Sagen wir es heißt common\components\EventBootstrap. Es muss BootstrapInterface implementieren, um ordnungsgemäß zu funktionieren.

namespace common\components; 

// Other namespaces from previous code 

use yii\base\BootstrapInterface; 

class EventBootstrap implements BootstrapInterface 
{ 
    public function bootstrap($app) 
    { 
     // Put the code above here 
    } 
} 

Dann müssen Sie es in config in Bootstrap-Abschnitt enthalten:

return [ 
    'bootstrap' => [ 
     'common\components\EventBootstrap', 
    ], 
]; 

Offizielle Dokumentation:

Zusätzliche Hinweise: Ich habe auch versucht, es nur über die Anwendungskonfiguration anzugeben, aber ohne Erfolg.

Ich habe keinen Weg gefunden, dort anzugeben.

Sie können sehen this question, aber das Verhalten ist an die gesamte Anwendung angeschlossen, die über Config möglich ist.

+1

Ihre Lösung ist großartig! Ich musste einige Änderungen vornehmen: 'Namespace' sollte über' use' sein, und 'property_exists' sucht nach einer öffentlichen Variable im Modell, also sollte es als' public $ created' deklariert werden, nicht als 'public $ created_at' weil mit '$ created_at' wird es null speichern – cku2014

+0

Bitte bearbeiten Sie Ihre Antwort, damit ich es als Lösung markieren kann. Vielen dank für Deine Hilfe.Und noch eine Sache, bitte machen Sie eine Korrektur von 'boostrap' nach' bootstrap' überall – cku2014

+1

Es kann auch 'EVENT_BEFORE_VALIDATE' verwendet werden, um die init procces nicht zu überladen, und nur bei Validierung zu laufen, was ein vor speichern Ereignis – cku2014

2

Ich weiß es ein bisschen alt Frage, aber wenn man in demselben Problem ist, werde ich teilen, was ich als saubere Möglichkeit gefunden habe, es zu tun. Ich definiere nur ein Verhalten in einem Merkmal. Ich benutze diese Eigenschaft nur in Modellen und das ist es. Es fügt nur eine Zeile im Modell hinzu, aber es ist sauberer und macht die Codepflege ein Kinderspiel.

Hier ist ein Beispiel Merkmal

<?php 

namespace common\traits; 

use Yii; 
use yii\behaviors\BlameableBehavior; 
use yii\behaviors\TimestampBehavior; 

trait Signature 
{ 

    public function behaviors() 
    { 
     return [ 
      [ 
       'class' => BlameableBehavior::className(), 
       'createdByAttribute' => 'created_by', 
       'updatedByAttribute' => 'updated_by', 
      ], 
      [ 
       'class' => TimestampBehavior::className(), 
       'createdAtAttribute' => 'created_at', 
       'updatedAtAttribute' => 'updated_at', 
       'value' =>function(){ 
        return time(); 
       }, 
      ], 
     ]; 
    } 
} 

und Modellcode

class Category extends \yii\db\ActiveRecord 
{ 
    use \common\traits\Signature; 
    // Model code here 
} 
+1

das sieht unheimlich und modern aus .. wird aber tatsächlich von PHP 5.4 + –

+0

unterstützt, wenn Sie 'function behaviours' in Category definieren. Es überschreibt das 'Signature'-Merkmal. Sieht gut aus, benötigt aber etwas mehr Flexibilität –

+0

Sie können eine bessere Version vorschlagen. Und ja, Eigenschaften sind neu, aber PHP> = 5.4 ist ruhig ein Standard jetzt :) –

Verwandte Themen