Yii Einleitung

Der Guide ist als Einleitung gedacht - aber nicht als Referenz.. er soll einen groben Überblick über die Funktionalität geben um später die richtigen Entscheidungen treffen zu können
Ganz unten befinden sich ein paar Links wo das ganze noch mehr vertieft wird.

Einleitung zu Yii:

Yii Guide
Die Dateistruktur wird mit einem Konsolen Kommando erstellt und ist immer gleich - das ist zwar manchmal nervig weil es tausend Ordner gibt, hilft aber deutlich dabei den Code strukturiert zu halten.
Eine wichtige Konvention ist, dass Klassennamen den Dateinamen entsprechen. Klassennamen werden im CamelCase geschrieben - fangen groß an und sind wie auch die db-Tabellen im Singular.
Klassen die mit C anfangen (CDbManager oder CController) sind core Klassen - und die mit E sind extensions..

Das Klassennamen den Dateinamen entsprechen ist wichtig, weil yii Lazy Loading benutzt - wir teilen Yii nur mit wo bestimmte Dateien zu finden sind und am Dateinamen weiß es welche Klasse sich darin befindet
Wenn du sagst new MyClass und hast die MyClass Klasse noch nirgendwo eingebunden sucht yii in einem vordefinierten Bereich (den gibt man ueber die config an oder z.b. mit Yii::import('application.components.Controller') oder auch 'application.components.*'


Nach dem Erstellen über das Konsolenkommando ist schon ein bisschen was da, damit man nicht bei 0 anfangen muss.. also ein bisschen design, content und sogar Login und Kontaktformular..

Ordnerstruktur

Die initiale Ordnerstruktur besteht aus:
  • index.php (jeder request läuft über diese Datei - sie lädt die Configs und initialisiert das Framework)
  • assets/ da sind css-Dateien und Bilder von Extensions oder Modulen aus dem protected Ordner - werden automatisch erstellt
  • css/ images/ js/ .. (die Ordner hab ich selber erstellt - theoretisch sollte man das ueber assets lösen)
  • protected/ (hier befinden sich alle Dateien die für die Seite relevant sind)
    • components/ (Wiederverwendbare Benutzerkomponenten)
    • controllers/ (Controller - dazu später mehr)
    • views/ (Views und Layout - dazu später mehr)
    • models/ (Modelle - dazu später mehr)
    • extensions/ (alle Erweiterungen hier rein - in meinen Augen macht es Sinn alle nichtprogramm-spezifischen generischen Lösungen dahin auszulagern
    • config/ (Alle Konfigurationsdateien)
    • runtime/ (temporäre Dateien (z.B. log)
    • tests/ (testfälle stehen hier drin)
    • modules/ (Module - die einzelnen module haben dann wieder die unterordner: components, controllers, views, models)

MVC erklärt

Wenn du Softwaretechnik hast kennst du es vielleicht - ein Designpattern, was grob gesagt die Daten von der Logik, von dem Design trennt
Man unterscheidet also in 3 Aufgabenbereiche die physisch voneinander getrennt werden (was z.B. Austauschbarkeit erhöht - aber auch der Übersichtlichkeit dient)

M = Model = Datenstruktur:

Bei mir bis jetzt immer ein ActiveRecord gewesen - es repräsentiert den Inhalt der DB und bietet grundlegende Funktionalität um mit diesen Daten zu arbeiten - z.B. getFormattedText() oder gibt an welche Attribute required und welche optional sind
Das Model ist für den Lösch-/Speicher-/Update- Vorgrang zuständig
Mehr dazu im ActiveRecord abschnitt

C = Controller = Logik:

Der Controller ist der erste Einstiegspunkt wenn eine Webseite aufgerufen wird (er ist indirekt für die Namen der Links zuständig).
Der Controller stellt Verknüpfungen zwischen den Objekten her und führt Operationen (z.B. Save) auf diesen aus..
Wenn keine Url-Rewrites eingesetzt werden, wird er mit: index.php?r=controllerName (also erste Buchstabe klein) aufgerufen.
Wenn der Controller in einem Modul drin ist wär es index.php?r=modul/controllerName

Actions


In einem Controller kann man verschiedene actions definieren z.B. actionIndex() actionEdit() Zugriff auf die Actions geht wieder ueber die Url r=controllerName/nameDerAction - wenn kein "actionName" in der url angegeben wurde, wird die default-action (meistens index) benutzt
Yii erkennt eine Action daran, dass der Funktionsname mit "action" beginnt und diese Funktion in einem Controller ist.

V = View = Design:

Der View repräsentiert eine einzelne Seite - es wird keine TemplateEngine verwendet.
In dem View sollen nur sehr einfache Statements vorkommen: echo, das Einbinden von Widgets, if, foreach.. aber auf jeden Fall sollen keine DB-Daten mehr geändert werden.
Variablen in einem View müssen als Parameter übergeben wurden. $this - repräsentiert den Controller und ist immer da.. Da ein View nur eine einzelne Seite ist und man manchmal Einfluss auf das Layout haben möchte (setzen der Metadaten z.b.) ist das ein sehr praktischer Weg.. das Layout selber ist auch nur ein view welcher wieder vom Controller erbt und den kleineren view per echo ausgiebt..

Alles zusammen

der request: index.php?r=myModule/myController/myAction wird wie folgt behandelt:
  1. Nachschlagen ob Modul "protected/modules/myModule" existiert
  2. Nachschlagen ob Controller "protected/modules/myModule/controllers/MyController.php" existiert
  3. Nachschlagen ob die Action "myAction" mit der Funktion "actionMyAction()" in der "MyController"-Klasse existiert
  4. actionMyAction ausfuehren - am Ende der Funktion steht jetzt $this->render('myView", array('test'=>$myTest));
  5. Nachschlagen ob der View "protected/modules/myModule/view/myController/myView.php" existiert
  6. Übergeben der Variable $myTest als $test an den View
  7. Layout Nachschlagen und den Inhalt des gerenderten Views dort einfügen (meist wird das Layout im components/Controller.php definiert



erweiterte Erläuterungen:

gii:

Zum Erstellen von Modulen, Models, Controllern (sind aber eigtl trivial), CRUD (Create, Read, Update, Delete) benutzen..
Erstellt eine Reihe an Boilerplate-Code den man nun nicht mehr per Hand erzeugen muss.. am effizientesten für Models, da dort die Datenbankstruktur ausgelesen wird.
Z.B. einen Lifecycle:
  1. DB Tabelle erstellen mit sovielen Informationen wie möglich.. z.B. auch foreign keys, primary key..
    wie schonmal gesagt Singular benutzen und auch eine gute Konvention ist es, bei Modulspezifischen Tabellen noch den Modulname per Unterstrich davor zu schreiben..
  2. Per Gii das Model dazu erstellen - Interface ist selbsterklärend.. Du musst noch manuell "generate" betätigen und nachher auch gucken, dass er nicht an den Dateirechten gescheitert ist.
  3. (CRUD erstellen) - ich mag die DefaultController und Views von dem Erstellten nicht besonders
  4. Anpassen (Wenn Crud verwendet wird kann man sich auch ueberlegen das default-crud template anzupassen - ist nicht so schwer)
Ein anderer Lifecycle wär noch das Erstellen eines Moduls, was aber sehr simpel ist.

ActiveRecord:

Meiner Meinung nach das beste Feature von Yii:
Jedes ActiveRecord repräsentiert eine DB Tabelle und vereinfacht durch magic-methods die Arbeit erheblich. Im Folgenden wird ein von gii erstelltes Model von oben nach unten erklärt:
  • function init() hat in Yii soweit ich weiß jede Klasse.. achtung: nicht vergessen noch parent::init() aufzurufen. Ist soetwas wie der Konstruktor nur ein µ später (Bei ActiveRecord macht es Sinn, da im Konstruktor ja noch das DB-Schema geladen werden muss)
  • rules() gibt ein array zurück - sagt welche Attribute unbedingt benoetigt werden (required) oder welche Attribute in einer massenzuweisung (dazu gleich) sicher sind (safe)
    Auch lassen sich Validierungsregeln wie Int,String,Email.. festlegen welche dann zur Benutzerinteraktion wichtig sind
    • mit 'on'=>'scenarioname' lassen sich diese Eigenschaften auch fuer bestimmte Szenarien angeben (z.b. sind bei einem Insert vllt mehrere Attribute required.. und bei einem update manche attribute vllt nicht mehr safe..)
    • Fehler den man gern macht: die Attribute müssen alle in einem String geschrieben werden array('id, name, datum', 'safe'), - nicht in mehreren
  • relations() Rückgabe wieder ein array - über die DB-Schlüssel sagt man in welcher relation es zu anderen Modellen steht (has_one MANY_MANY...) - man kann dann auf die Relation wie auf ein Attribut zugreifen
    Namenskonvention: hier denk ich ist es nicht verkehrt getRelationName zu benutzen - Einzahl für HAS_ONE und Mehrzahl für die anderen
  • protected beforeUpdate(), beforeInsert(), beforeDelete() und das ganze auch als after-Version.. praktikabel um z.b. die userid einem model Attribut einzusetzen oder evtl auch eigene Rules dort mit einzubauen.
    Bei einem delete können auch andere Relationen mitgelöscht werden oder Dateien die zu dem Model gehören zu entfernen
    nicht vergessen den parent::beforeXYZ() und parent::afterXYZ() mit aufzurufen

Active-Record Magie:

Jedes mal wenn die Klasse aufgerufen wird, lädt es sich aus der zugehörigen Tablle alle Spaltennamen in den internen Speicher und man kann dann mit $model->spaltenname auf die Werte der Spalte zugreifen.
genauso lassen sich mit $model->attributes = array('spalte1'=>'wert1', 'spalte2'=>123); Massenzuweisungen durchfuehren (welche nur Werte setzen wenn die Attribute als safe deklariert wurden.
Einzelzuweisungen einfach mit $model->spaltenname = '123'; - hier wird die "safe" Regel umgangen-
Zum Speichern ruft man $model->save() auf.. oder auch
if($model->validate())$model->save(false);
Um auf die Relationen zuzugreifen haben wir jeder Relation einen Namen gegeben und können dann einfach mit $model->myRelationName zugreifen und haben dann wieder ein neues Modell oder ein Array von Modellen

Module:

Am besten automatisch erstellen lassen: ist eigtl das was sich in protected befindet nochmal nach modules kopiert.. quasi ein kleines Subsystem, was einfach abgetrennt werden kann oder auch wieder Subsysteme besitzen kann..
Zugriff auf Module per index.php?r=modulName/controllerName/actionName

Extensions:

auf yiiframework.com gibt es einige.. aber nicht davon ausgehen, dass das niveau vom Code gut ist.. oft ist es nur so, dass sie funktionieren.. Was ich mitbekommen habe: yiiExt von SamDark hat eine sehr gute Qualität, Tydeas und Thyseus Extensions sind meist auch recht gut.

Sonstiges

  • Links immer mit CHtml::link() darstellen, da die dann intern vom Urlmanager überschrieben werden können
  • Formulare - im bisherigen Code schauen wie das gelöst werden kann
  • Achtung bei der Ausgabe von Strings.. manche werden per htmlentities (dafuer gibts auch eine yii Funktion) kodiert andere wiederum nicht.. also $model->attributName ist auf jeden fall nicht kodiert, aber wenn du in einem formular $model->getLabel('blub') machst schon..
  • CSS und Javascript includes lassen sich auch mit einer Funktion des ScriptManager einbinden - die den include in den header der erzeugten Htmldatei reinschreibt
  • components/Controller ist der standardcontroller wovon alle anderen erben. Dieser Controller ist z.B. für das Layout zuständig und bietet generische Funktionalität

Assets:

Sind Ordner mit Media-Daten wie Bilder und css. Da der protected Ordner per htaccess geschützt wird.. Ist aber nicht besonders Entwicklerfreundlich, da er sich nur refresht, wenn er die Datei im bereits published Assetfolder nicht findet.. also müsste man beim Entwickeln immer wieder löschen. - Deshalb ist bis jetzt alles unter /css usw abgelegt

behavior:

Erlaubt das Hinzufügen von Funktionalität ohne von der Klasse erben zu müssen.

Javascript

Yii hat per default bereits jede Menge ajax/javascript widgets eingebaut. Es gibt auch viele Extensions dazu - auf jeden fall sollte man bevor man etwas eigenes schreibt nachsehen was es bereits von yii gibt - und wenn es doch etwas eigenes wird evtl gleich selber eine Extension schreiben - ist nicht besonders schwer.

Tests

	
wget http://selenium.googlecode.com/files/selenium-remote-control-1.0.3.zip
unzip selenium-remote-control-1.0.3.zip
cd selenium-remote-control-1.0.3
java -jar selenium-server.jar

cd protected/tests
vim WebTestCase.php #set url
vim phpunit.xml #set browser
	

Literaturliste

Dieses Yii-buch ist ganz OK zum kennen lernen.. ich kannte zwar schon das meiste.. aber was ich gelernt hab ist wie man an das Testing rangehen sollte..
Was du lernen kannst: wie man so an das Entwickeln eines Projektes rangeht..
Was fehlt: teilweise hat er garnichts dazu geschrieben warum eine Funktion bestimmte Parameter bekommt oder was dies und das jetzt bewirkt.. auch ist es nur sehr oberflächlich.. Oft ist es ein Rätsel für mich, wie intern bestimmte Dinge umgesetzt wurden.. z.B. http://code.google.com/p/yii/issues/detail?id=289 war ich überrascht, dass das nicht so gehandhabt wird. - Auf solche details nimmt er halt keinen bezug - damit ist es eher ein Anfängerhandbuch mit vertiefendem testing-wissen

Yii Guide sehr zu empfehlen ist von den Entwicklern selber geschrieben und sehr benutzerfreundlich.
Yii Api auch sehr zu empfehlen
Yii Introduction Damit hab ich Yii gelernt.