Da eine Erweiterung auch von anderen Entwicklern verwendet werden soll, erfordert ihre Erstellung etwas zusätzlichen Aufwand. Hier einige grundsätzliche Richtlinien:
Wir beschreiben im Folgenden, wie Sie eine neue Erweiterung entsprechend den Kategorien in der Übersicht erstellen können. Die Erläuterungen sind auch für Erweiterungen gültig, die Sie hauptsächlich für Ihre eigenen Projekt erstellen.
Eine Anwendungskomponente sollte das Interface IApplicationComponent implementieren oder die Klasse CApplicationComponent erweitern. Die wichtigste zu implementierende Methode ist IApplicationComponent::init, in der die Komponente ihre Initialisierung vornehmen kann. Diese Methode wird aufgerufen, nachdem die Komponente erstellt und ihr die Startwerte ihrer Eigenschaften (entsprechend der Anwendungskonfiguration) zugewiesen wurden.
Standardmäßig wird eine Komponente nur erstellt und initialisiert, wenn zum ersten mal auf sie zugegriffen wird. Falls eine Anwendungskomponente unmittelbar nach der Anwendungsinstanz erzeugt werden muss, sollte der Anwender sie in der Eigenschaft CApplication::preload aufführen.
Um ein Behavior zu erstellen, muss das IBehavior-Interface implementiert werden. Bequemerweise enthält Yii bereits die Basisklasse CBehavior, die dieses Interface implementiert und einige weitere Komfortfunktionen anbietet. Kindklassen müssen hauptsächlich die Methoden implementieren, die sie ihren Komponenten bereitstellen wollen.
Wenn man Behaviors für CModel und CActiveRecord entwickeln möchte, kann man auch CModelBehavior bzw. CActiveRecordBehavior erweitern. Diese Basisklassen bieten zusätzliche, an CModel bzw. CActiveRecord angepasste Features. Die CActiveRecordBehavior-Klasse implementiert z.B. eine Reihe von Methoden, die auf die Events im Lebenszyklus eines ActiveRecord-Objekts reagieren. Eine Kindklasse kann diese Methoden überschreiben, um so angepassten Code einzuschleusen, der im Lebenszyklus eines AR ausgeführt wird.
Der folgende Code zeigt ein Beispiel eines ActiveRecord-Behaviors. Wenn dieses
Behavior an ein AR-Objekt angebunden und dann dessen save()
-Methode
aufgerufen wird, setzt es automatisch die Attribute create_time
und
update_time
auf den aktuellen Zeitstempel.
class TimestampBehavior extends CActiveRecordBehavior
{
public function beforeSave($event)
{
if($this->owner->isNewRecord)
$this->owner->create_time=time();
else
$this->owner->update_time=time();
}
}
Ein Widget sollte CWidget oder dessen Kindklassen erweitern.
Am einfachsten erstellt man ein Widget, indem man ein vorhandenes Widget erweitert und seine Methoden oder vorgegebenen Eigenschaften überschreibt. Wenn Sie z.B. schönere CSS-Stile für CTabView verwenden möchten, könnten Sie dessen CTabView::cssFile-Eigenschaft konfigurieren. Sie könnten CTabView aber auch wie im folgenden Beispiel erweitern, so dass Sie diese Eigenschaft beim Einsatz des Widgets nicht mehr angeben müssen.
class MyTabView extends CTabView
{
public function init()
{
if($this->cssFile===null)
{
$file=dirname(__FILE__).DIRECTORY_SEPARATOR.'tabview.css';
$this->cssFile=Yii::app()->getAssetManager()->publish($file);
}
parent::init();
}
}
Hier überschreiben wir die Methode CWidget::init und weisen
CTabView::cssFile die URL für unsere neue CSS-Datei zu, falls diese
Eigenschaft noch nicht gesetzt war. Wir legen die neue CSS-Datei im selben
Verzeichnis ab, das auch die Klassendatei von MyTabView
enthält, damit beide als
Erweiterung zusammengepackt werden können. Da die CSS-Datei vom Web aus nicht
zugänglich ist, müssen wir sie als Asset veröffentlichen.
Um ein ganz neues Widget zu erstellen, müssen wir hauptsächlich zwei Methoden
implementieren: CWidget::init und CWidget::run. Erstere wird aufgerufen,
wenn wir $this->beginWidget
verwenden, um ein Widget in einem View
einzusetzen, die Zweite, wenn wir $this->endWidget
aufrufen. Falls wir den
eingebetteten Inhalt zwischen den beiden Aufrufen abfangen und verarbeiten
möchten, können wir in CWidget::init eine
Ausgabepufferung
starten und die gepufferte Ausgabe in CWidget::run zur weiteren
Bearbeitung auslesen.
Ein Widget erfordert oftmals die Einbindung von CSS-, Javascript- oder anderen Dateien in eine Seite. Diese Dateien nennen wir Assets (sinngem.: Anlage, Zusatz), da sie am Ort der Widget-Klasse abgelegt werden und normalerweise für Web-Besucher nicht erreichbar sind. Um diese Dateien vom Web aus zugänglich zu machen, müssen wir sie mit CWebApplication::assetManager (sinngem.: Anlagenverwalter) veröffentlichen, wie im obigen Codebeispiel gezeigt. Wenn wir eine CSS- oder Javascript-Datei außerdem in die aktuelle Seite einbinden möchten, müssen wir sie mit CClientScript registrieren:
class MyWidget extends CWidget
{
protected function registerClientScript()
{
// ...CSS- oder Javascript-Datei hier veröffentlichen...
$cs=Yii::app()->clientScript;
$cs->registerCssFile($cssFile);
$cs->registerScriptFile($jsFile);
}
}
Ein Widget kann auch seine eigenen View-Dateien verwenden. In diesem Fall
legen Sie ein Verzeichnis namens views
unterhalb des Ordners an, der die
Klassendatei des Widgets enthält. Legen Sie alle zugehörigen View-Dateien dort ab.
Ähnlich wie im Controller können Sie dann in der Widget-Klasse
$this->render('ViewName')
benutzen, um einen View zu rendern.
Eine Action sollte CAction oder deren Kindklassen erweitern. Die wichtigste zu implementierende Methode für eine Action ist IAction::run.
Ein Filter sollte von CFilter oder dessen Kindklassen abgeleitet werden. Die beiden wichtigsten zu implementierenden Methoden für einen Filter sind CFilter::preFilter und CFilter::postFilter. Erstere wird aufgerufen, bevor eine Action ausgeführt wird, letztere danach.
class MyFilter extends CFilter
{
protected function preFilter($filterChain)
{
// Logik, die vor dem Aufruf der Action ausgeführt wird
return true; // false, falls die Action nicht ausgeführt werden soll
}
protected function postFilter($filterChain)
{
// Logik, die nach dem Aufruf der Action ausgeführt wird
}
}
Der Parameter $filterChain
(Filterkette) ist vom Typ CFilterChain und
enthält Informationen über die gerade zu filternde Action.
Wenn ein Controller als Erweiterung
veröffentlicht werden soll, sollte er CExtController statt CController
erweitern. Und zwar hauptsächlich deshalb, weil ein CController seine
View-Dateien unter application.views.ControllerID
sucht, während
CExtController seine View-Dateien im Unterverzeichnis views
des Ordners
erwartet, der auch die Klassendatei des Controllers enthält. Dadurch wird es
einfacher, den Controller weiterzugeben, da seine View-Dateien bei der
Klassendatei verbleiben.
Ein Validator sollte CValidator erweitern und dessen Methode CValidator::validateAttribute implementieren.
class MyValidator extends CValidator
{
protected function validateAttribute($model,$attribute)
{
$value=$model->$attribute;
if($value has error)
$model->addError($attribute,$errorMessage);
}
}
Ein Konsolenbefehl sollte CConsoleCommand erweitern und dessen Methode CConsoleCommand::run implementieren. Optional können wir auch CConsoleCommand::getHelp überschreiben, um eine nützliche Hilfe zum Befehl anzuzeigen.
class MyCommand extends CConsoleCommand
{
public function run($args)
{
// $args ist ein Array mit den Kommandozeilenargumenten dieses Befehls
}
public function getHelp()
{
return 'Anleitung: Wie Sie diesen Befehl verwenden';
}
}
Für Details zur Erstellung von Modulen, beachten Sie bitte das Kapitel über Module.
Die allgemeine Richtlinie für die Entwicklung eines Moduls lautet: Es sollte in sich geschlossen sein. Sämtliche Dateien, die vom Modul verwendet werden (wie z.B. CSS-, Javascript-, Bilddateien) sollten zusammen mit dem Modul geliefert werden. Und sie sollten vom Modul veröffentlicht werden, um sie vom Web aus zugänglich zu machen.
Eine allgemeine Erweiterungskomponente zu entwickeln, bedeutet, eine Klasse zu schreiben. Auch hier gilt: Die Komponente sollte in sich geschlossen sein, so dass sie von anderen Entwicklern einfach eingesetzt werden kann.
Signup or Login in order to comment.