Monatliches Archiv: November 2014

Yii2 Modul override Controller, Model, Views

Yii2 Controllers

In Yii2 gibt es die Möglichkeit Module etc. über composer zu installieren. In der Regel werden sowohl alle Composer Yii2 erweiterungen als auch eigens kopierte Yii2 Module im Verzeichnis „vendor“ abgelegt. Ich gehe hier davon aus dass ein Yii2 Modul „user“ installiert wurde und beispielsweise beim aufrufen der User-Übersicht weitere Daten im Controller geladen werden sollen. Im ersten Schritt erstellen wir also einen Controller der genau dies tut. Wir nennen Ihn hier einfach ExtendedUserController. Nun möchte ich aber nicht das gesamte Yii2 Modul „user“ in meinen frontend Ordner kopieren. Hierzu können wir in unserer Yii2 Konfiguration zusätzlich eine ControllerMap angeben. Dies sieht wie folgt aus:

1
2
3
4
5
6
7
8
  'modules'    => [
    'user' => [
      'class'         => '\vendorname\modules\user\UserModule',
      'controllerMap' => [
        'user' => 'frontend\controllers\ExtendedUserController',
      ],
    ],
  ],

In unserer actionIndex möchten wir nun eine zusätzliche Aktion ausführen bevor wir den View rendern. Hierzu können wir jetzt unsere actionIndex einfach simpel überschreiben.

1
2
3
4
  public function actionIndex() {
    // Aktion die wir ausführen möchten
    return parent::actionIndex();
  }

Über parent::actionIndex() können wir die Originalversion der actionIndex() ansteuern. Möchten wir allerdings andere Daten an den View übergeben oder überhaupt eine vollkommen andere View-Datei rendern, müssen wir uns den Code der Originaldatei kopieren und einfach anpassen. Den aufruf parent::actionIndex() lassen wir dann weg.

 

Yii2 Models

Selbiges wie bei den Controllers geht auch bei den Models. Da dieses Thema in der Regel nicht ganz so Wichtig ist wie die Controller möchte ich nur ganz kurz darauf eingehen. Wir gehen davon aus dass wir ein Model „User“ in unserem user Modul haben. Auch diese Klasse erweitern wir in dem wir eine neue Klasse ExtendedUser erstellen die von der Ursprungsklasse User abstammt. Nun können wir in unserer Konfiguration wie bei den Controller auch die Models angeben:

1
2
3
4
5
6
7
8
9
10
11
12
    'modules' => [
        'user' => [
            'class' => 'vendorname\modules\user\UserModule',
            'components' => [
                'manager' => [
                    // Active record classes
                    'userClass'    => 'frontend\models\ExtendedUser',
                ],
            ],
        ],
        ...
    ],

 

Yii2 Views

Was allerdings für Controller und Models gilt, gilt natürlich auch für Views. Und genau dies ist extrem hilfreich. Gerade wenn man viele und auch gerne fremde Module einsetzt. So hat man die Möglichkeit eigene Ansichten für das fremde Yii2 Modul zu erstellen. Hierzu suchen wir uns den entsprechenden View im Modul raus und geben in der Konfiguration an dass wir hier einen eigenen View haben auf den zurück gegriffen werden soll. Mit folgendem Code sagen wir dass die View Files in unserem themes Ordner zu finden sind:

1
2
3
4
5
6
7
8
9
  'components' => [
    'view' => [
      'theme' => [
        'pathMap' => [
          '@vendor/modules/user/views' => '@app/themes/user/views'
        ],
      ],
    ],
  ],

Nun müssen wir nur noch den entsprechenden View Ordner aus dem Modul kopieren und können nun für das Modul jeweils vollkommen eigene Ansichten machen. In Verbindung zum ersten Abschnitt in dem wir einen Controller (und Model) erweitern, haben wir hier zum umgestalten von fremden Modulen vollkommene Freiheit.

 

Warum?

Warum sollten wir das jedoch so machen? Nun zum einen ist es vollkommen sauber getrennt was unser Code ist und was fremder Code ist. Allerdings haben wir noch einen viel wichtigeren Vorteil dadurch. Alle Yii2 Module und Erweiterungen die wir Beispielsweise über Composer installieren sind weiterhin vollkommen Updatefähig. Wir können uns also jederzeit die neuesten Updates der Erweiterungen über Composer holen und unsere Ansichten werden davon nicht beeinflusst.

YII2 Url Generierung

Seit nun ein paar Wochen ist jetzt Yii2 schon auf dem Markt. So wird es Zeit dass ich euch von Yii2 meine Erfahrungen zeige. Da ich mir erst einmal einige Gedanken machen musste bis ich die erste Url in Yii2 aufgebaut hatte möchte ich euch hier einige Möglichkeiten aufzeigen.

Wenn eine Funktion eine Url erwartet kann man diese einfach in der short Array Syntax angeben. So erstellt man einen Link auf die Action „Login“ des „Site“-Controllers wie folgt:

1
Html::a('Login', ['login'])

Dabei kommt ein Link „index.php?r=site/login“. Möchte man nun auf einen anderen Controller verweisen so gibt man die Url mit einem führenden Slash an. Dies ist gleich geblieben zu Yii 1, jedoch wird in Yii2 dies via short Array Syntax notiert. Wenn wir nun auf den Controller „User“ verweisen möchten, müssen wir dies wie folgt tun:

1
Html::a('Login', ['/user/login'])

Hier erhalten wir einen Link der sich ähnlich wie folgender aufbauen wird „index.php?r=user/login“. Wir möchten jedoch noch einen Schritt weiter gehen und einen Parameter „frontend“ mit dem Wert 1 übergeben. Dies erledigen wir in dem wir ein weiteres Element in das Array einfügen.

1
Html::a('Login', ['/user/login', 'frontend'=>1])

So können wir beliebige Parameter mit der Url weitergeben. Dies war jetzt alles sehr ähnlich wie in Yii1. Wenn wir jedoch nun eine einfache URL generieren möchten ohne weiteres Markup herum so machen wir dies mit der URL-Klasse von Yii. Weitere Informationen zu dieser Klasse können unter folgendem Link aufgerufen werden.

1
2
use yii\helpers\Url;
Url::to(['/user/login']);

So erhalten wir ebenfalls einen verweis zu „index.php?r=user/login“. Jedoch erhalten wir dieses mal nicht ein komplettes Html-Tag mit Label etc. sondern lediglich die reine Url. Diese können wir selbst weiterverwenden. Beispielsweise wenn wir über normales HTML einen Link erstellen. Dabei verhält sich der erste Parameter von Url::to() gleich zu dem zweiten Parameter von HTML::a().

Wenn wir nun noch folgenden Code in unserer Yii2 Konfiguration unter „Components“ mit einbinden:

1
2
3
4
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
],

Dann erhalten wir eine Url die ähnlich folgender aussehen wird „http://domain.tld/user/login“