0 follower

ActiveRecord

Obwohl man mit Yii-DAO praktisch jede datenbankbezogene Aufgabe erledigen kann, werden wir wahrscheinlich 90% unserer Zeit mit dem Schreiben von SQL-Anweisungen für die üblichen CRUD-Operationen (create, read, update und delete) verbringen. Auch die Codewartung wird erschwert, wenn dieser mit SQL Anweisungen durchmischt ist. Zur Lösung dieser Probleme können wir ActiveRecord nutzen.

ActiveRecord (AR) ist eine gängige objektrelationale Abbildungstechnik (engl.: object-relational mapping,ORM). Jede AR-Klasse repräsentiert eine Tabelle der Datenbank (oder einen View) deren Attribute durch AR-Klasseneigenschaften repräsentiert werden. Eine AR-Instanz repräsentiert eine Zeile in der Tabelle. Übliche CRUD-Operationen sind als AR-Methoden implementiert. Das hat zur Folge, dass wir in eher objektorientierter Weise auf unsere Daten zugreifen können. Zum Beispiel können wir den folgenden Code dazu benutzen, um eine neue Zeile in die Post-Tabelle einzufügen:

$post=new Post;
$post->title='Beispielbeitrag';
$post->content='Inhalt des Beitrags';
$post->save();

Im Folgenden beschreiben wir, wie wir AR-Instanzen anlegen und für CRUD-Operationen benutzen können. Im nächsten Kapitel werden wir dann darauf eingehen, wie wir AR verwenden können, um mit Beziehungen in einer Datenbank (DB) umzugehen. Der Einfachheit halber benutzen wir für die Beispiele in diesem Abschnitt folgende Datenbanktabelle. Beachten Sie bitte, dass sie im folgenden SQL AUTOINCREMENT durch AUTO_INCREMENT ersetzen müssen, falls Sie MySQL verwenden.

CREATE TABLE Post (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    title VARCHAR(128) NOT NULL,
    content TEXT NOT NULL,
    createTime INTEGER NOT NULL
);

Hinweis: AR ist nicht dafür gedacht, alle datenbankbezogenen Aufgaben zu lösen. AR ist zweckmäßig, um Datenbanktabellen in PHP abzubilden sowie für Abfragen, die kein komplexes SQL erfordern. In komplexeren Fällen sollte Yii-DAO benutzt werden.

1. Aufbau einer DB-Verbindung

AR setzt auf eine DB-Verbindung auf, um DB-bezogene Operationen durchzuführen. Standardmäßig geht AR davon aus, dass die Applikationskomponente db die notwendige CDbConnection-Instanz liefert, die als DB-Verbindung dient. Die folgende Applikationskonfiguration zeigt ein Beispiel:

return array(
    'components'=>array(
        'db'=>array(
            'class'=>'system.db.CDbConnection',
            'connectionString'=>'sqlite:path/to/dbfile',
            // Schema Caching einschalten, um die Performance zu verbessern
            // 'schemaCachingDuration'=>3600,
        ),
    ),
);

Tipp: ActiveRecord verwendet Metadaten von Tabellen, um die Spalteninformationen zu ermitteln. Das Lesen und Analysieren dieser Daten braucht Zeit. Falls das Schema Ihrer Datenbank kaum mehr geändert wird, sollten Sie das Schema-Caching einschalten, indem Sie die Eigenschaft CDbConnection::schemaCachingDuration auf einen Wert größer 0 setzen.

Die AR-Unterstützung ist auf bestimmte Datenbankmanagementsysteme (DBMS) begrenzt. Derzeit werden folgende DBMS unterstützt:

Hinweis: Microsoft SQL Server wird seit Version 1.0.4 unterstützt und Oracle seit Version 1.0.5.

Falls Sie eine andere Applikationskomponente als db benutzen möchten, oder wenn Sie mit AR auf mehreren Datenbanken arbeiten, sollten Sie CActiveRecord::getDbConnection() überschreiben. Die CActiveRecord-Klasse ist die Basisklasse für alle AR-Klassen.

Tipp: Es gibt zwei Wege, um mit AR auf mehren Datenbanken zu arbeiten. Falls die Datenbankschemas sich unterscheiden, können Sie unterschiedliche AR-Basisklassen mit verschiedenen Implementierungen von getDbConnection() erzeugen. Andernfalls ist es günstiger, die statische Variable CActiveRecord::db dynamisch zu ändern.

2. Definieren von AR-Klassen

Um auf eine Datenbanktabelle zuzugreifen, müssen wir zuerst eine AR-Klasse durch Erweitern von CActiveRecord definieren. Jede Klasse repräsentiert eine einzelne Datenbanktabelle, und eine AR-Instanz repräsentiert eine Zeile der Tabelle. Das folgende Beispiel zeigt den nötigen Mindestcode einer AR-Klasse, die die Tabelle Post repräsentiert.

class Post extends CActiveRecord
{
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
}

Tipp: Da AR-Klassen oft an vielen Stellen verwendet werden, können wir das ganze Verzeichnis mit AR-Klassen importieren, anstatt diese einzeln einzubinden. Liegen beispielsweise alle unsere AR-Klassen im Verzeichnis protected/models, können wir die Applikation wie folgt konfigurieren:

return array(
  'import'=>array(
      'application.models.*',
  ),
);

Standardmäßig hat die AR-Klasse den gleichen Namen wie die Datenbanktabelle. Überschreiben Sie die tableName()-Methode, falls sie sich unterscheiden sollen. Die model()-Methode wird in jedem AR deklariert (worauf wir in Kürze eingehen werden).

Über die Eigenschaften der entsprechenden AR-Instanz, kann auf die Felder einer Tabellenzeile zugegriffen werden. Der folgende Code setzt zum Beispiel das title-Feld (Attribut).

$post=new Post;
$post->title='Ein Beispielbeitrag';

Obwohl die title-Eigenschaft in der Post-Klasse nicht explizit deklariert wurde, können wir doch mit dem obigen Code auf sie zugreifen. Das liegt daran, dass title ein Feld in der Post-Tabelle ist und CActiveRecord mittels der magischen PHP Methode __get() erlaubt, darauf wie auf eine Eigenschaft zuzugreifen. Falls wir auf diese Weise versuchen, ein nicht existierendes Feld anzusprechen, wird eine Exception ausgelöst.

Info: In diesem Handbuch benennen wir Spalten in sog. CamelCase-Schreibweise (z.B. createTime), da sie wie normale Objekteigenschaften angesprochen werden, die ja ebenfalls CamelCase verwenden. Während dies für mehr Konsistenz in unserem PHP-Code sorgt, kann es auf der anderen Seite bei manchen Datenbanksystemen zu Problemen führen. Bei PostgreSQL spielt die Groß-/Kleinschreibung zum Beispiel standardmäßig keine Rolle und wir müssen eine Spalte in Anführungszeichen setzen, falls sie gemischte Groß-/Kleinschreibung verwendet. Es kann daher ratsam sein, Spalten- und Tabellennamen nur in Kleinbuchstaben zu benennen (z.B. create_time) um möglichen Problemen mit der Schreibweise vorzubeugen.

3. Einfügen von Datensätzen

Um eine neue Zeile in eine Datenbanktabelle einzufügen, erzeugen wir eine neue Instanz der entsprechenden AR-Klasse, setzen die den Tabellenfeldern entsprechenden Eigenschaften und rufen die save()- Methode auf, um das Einfügen abzuschließen.

$post=new Post;
$post->title='Beispielbeitrag';
$post->content='Inhalt des Beispielbeitrags';
$post->createTime=time();
$post->save();

Wird der Primärschlüssel automatisch vergeben (auto-increment), enthält die AR-Instanz nach dem Einfügen den aktuellen Primärschlüssel. Im obigen Beispiel spiegelt die id-Eigenschaft den Wert des Primärschlüssels für den neu eingefügten Beitrag wieder, obwohl wir diese Eigenschaft nicht explizit gesetzt haben.

Falls für eine Tabellenspalte im Schema ein statischer Vorgabewert definiert wurde (z.B. ein String oder eine Zahl), enthält die AR-Instanz nach dem Anlegen automatisch diesen Wert. Eine Möglichkeit, um diesen Vorgabewert zu verändern, besteht darin, diese Eigenschaft explizit in der AR-Klasse festzulegen:

class Post extends CActiveRecord
{
    public $title='Bitte den Titel eingeben';
    ......
}
 
$post=new Post;
echo $post->title;  // Dies führt zur Anzeige von: Bitte den Titel eingeben

Seit Version 1.0.2 kann man einem Attribut auch einen Wert vom Typ CDbExpression zuweisen, bevor der Datensatz in der Datenbank gespeichert wird. Um zum Beispiel einen Zeitstempel zu speichern, wie er von der MySQL-Funktion NOW() geliefert wird, können wir folgenden Code verwenden:

$post=new Post;
$post->createTime=new CDbExpression('NOW()');
// $post->createTime='NOW()'; funktioniert nicht
// 'NOW()' würde wie ein String behandelt
$post->save();

Tipp: Obwohl uns AR erlauben, Datenbankoperationen ohne umständliche SQL-Ausdrücke durchzuführen, möchten wir oft wissen, welche SQL-Abfragen tatsächlich von AR ausgeführt werden. Dies kann durch Aktivieren des Log-Features von Yii erreicht werden. Wir können zum Beispiel CWebLogRoute in der Anwendungskonfiguration einschalten und sehen dann am Ende jeder Webseite die ausgeführten SQL-Abfragen. Seit Version 1.0.5 können wir CDbConnection::enableParamLogging in der Anwendungskonfiguration auf true setzen, um auch die Parameter, die an die SQL-Abfragen gebunden werden, zu loggen.

4. Lesen von Datensätzen

Um Daten aus der Datenbanktabelle zu lesen rufen wir eine der folgenden find-Methoden auf:

// Finde die erste Zeile, die die angegebene Bedingung erfüllt
$post=Post::model()->find($condition,$params);
// Finde die Zeile mit dem angegebenen Primärschlüssel
$post=Post::model()->findByPk($postID,$condition,$params);
// Finde die Zeile mit den angegeben Attributwerten
$post=Post::model()->findByAttributes($attributes,$condition,$params);
// Finde die erste Zeile unter Anwenden der angegeben SQL-Anweisung
$post=Post::model()->findBySql($sql,$params);

Oben rufen wir die find-Methode mit Post::model() auf. Wie bereits erwähnt, wird die statische Methode model() für jede AR-Klasse benötigt. Die Methode gibt eine AR-Instanz zurück, die dazu benutzt wird, um in einem Objektkontext auf Methoden auf Klassenebene zugreifen zu können (ähnlich zu statischen Klassenmethoden).

Wenn die find-Methode eine Zeile findet, die die Abfragebedingung erfüllt, gibt sie eine Post-Instanz zurück, deren Eigenschaften die entsprechenden Werte der Felder der Zeile enthalten. Wir können die geladenen Werte dann wie Eigenschaften von normalen Objekten auslesen, z.B. echo $post->title;.

Falls in der Datenbank zur gegebenen Abfragebedingung nichts gefunden wird, gibt die find-Methode null zurück.

Beim Aufruf von find verwenden wir $condition und $params um Abfragebedingungen anzugeben. Dabei kann $condition ein String sein, der die WHERE-Klausel in einer SQL Abfrage darstellt und $params ein Array aus Parametern, dessen Werte an die Platzhalter in $condition gebunden werden. Zum Beispiel:

// Finde die Zeile mit postID=10
$post=Post::model()->find('postID=:postID', array(':postID'=>10));

Hinweis: Bei manchen Datenbanksystemen muss die postID-Spalte in obigem Beispiel escaped werden. Verwenden wir zum Beispiel PostgreSQL, müssten wir die Kondition als "postID"=:postID schreiben, da PostgreSQL standardmäßig die Groß-/Kleinschreibung von Spaltennamen nicht berücksichtigt.

Wir können $condition auch für komplexere Abfragebedingungen verwenden. Statt eines Strings kann $condition auch eine Instanz von CDbCriteria sein, die es uns erlaubt, weitere Bedingungen statt nur der WHERE-Klausel anzugeben, z.B.:

$criteria=new CDbCriteria;
$criteria->select='title';  // Nur die 'title' Spalte wird ausgewählt
$criteria->condition='postID=:postID';
$criteria->params=array(':postID'=>10);
$post=Post::model()->find($criteria); // $params ist nicht nötig

Beachten Sie, dass der $params-Parameter nicht mehr benötigt wird, wenn Sie CDbCriteria als Abfragebedingung nutzen, da diese Parameter, wie oben gezeigt, in CDbCriteria angegeben werden können.

Alternativ zur Verwendung von CDbCriteria kann auch ein Array an die find-Methode übergeben werden. Die Schlüssel und Werte des Array entsprechen den Namen und Werten der Eigenschaften von CDbCriteria. Das obige Beispiel kann daher wie folgt umformuliert werden:

$post=Post::model()->find(array(
    'select'=>'title',
    'condition'=>'postID=:postID',
    'params'=>array(':postID'=>10),
));

Info: Wenn bei einer Abfrage nach bestimmten Werten für Tabellenspalten gesucht werden soll, können wir dazu findByAttributes() verwenden. Dabei ist der Parameter $attributes ein Array von Werten, die durch Spaltennamen indiziert werden. In einigen Frameworks wird diese Aufgabe durch Aufruf von Methoden wie findByNameAndTitle gelöst. Obwohl diese Herangehensweise zunächst reizvoll aussieht, sorgt sie oft für Verwirrung, Konflikte und Probleme im Zusammenhang mit der Groß-/Kleinschreibung von Spaltennamen.

Wenn mehrere Datenzeilen die Abfragebedingung erfüllen, können wir diese gesammelt mit den folgenen findAll-Methoden beziehen, von denen jede ihr Pendant bei den schon beschriebnen find-Methoden hat.

// Finde alle Zeilen, die die angegebene Bedingung erfüllen
$posts=Post::model()->findAll($condition,$params);
// Finde alle Zeilen mit dem angegebenen Primärschlüsseln
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
// Finde alle Zeilen mit den angegeben Attributwerten
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
// Finde alle Zeilen unter Anwendung der angegeben SQL-Anweisung
$posts=Post::model()->findAllBySql($sql,$params);

Falls die Abfragebedingung von keiner Zeile erfüllt wird, liefert findAll ein leeres Array zurück. Dies unterscheidet sich von find, das null zurückliefert, falls nichts gefunden wurde.

Zusätzlich zu den oben beschriebenen find- und findAll-Methoden, werden für bequemen Zugriff noch die folgenden Methoden bereitgestellt:

// Liefert die Anzahl der Zeilen, die die angegebene Bedingung erfüllen
$n=Post::model()->count($condition,$params);
// Liefert die Anzahl der Zeilen durch Anwenden der angegeben SQL-Anweisung
$n=Post::model()->countBySql($sql,$params);
// Prüft, ob mindestens eine Zeile die angegebene Bedingung erfüllt
$exists=Post::model()->exists($condition,$params);

5. Aktualisieren von Datensätzen

Nachdem eine AR-Instanz mit den Werten der Tabellenspalten befüllt wurde, können wir diese verändern und in die Datenbanktabelle zurück speichern.

$post=Post::model()->findByPk(10);
$post->title='Titel eines neuen Beitrags';
$post->save(); // Änderung in der Datenbank speichern

Wie wir sehen, verwenden wir für Einfüge- und Aktualisierungsoperationen die gleiche save()-Methode. Wenn eine AR-Instanz durch den new-Operator erzeugt wurde, fügt der Aufruf von save() eine neue Zeile in die Datenbanktabelle ein. Falls die AR-Instanz das Ergebnis eines find- oder findAll-Aufrufs war, aktualisiert der Aufruf von save() die bestehende Zeile in der Tabelle. Wir können CActiveRecord::isNewRecord abfragen, um herauszufinden, ob wir eine neue AR-Instanz vorliegen haben oder nicht.

Es ist auch möglich, eine oder mehrere Zeilen in der Datenbanktabelle zu aktualisieren ohne sie vorher zu laden. AR bietet dazu auf Klassenebene folgende nützliche Methoden:

// Aktualisiere die Zeilen, die die angegebene Bedingung erfüllen
Post::model()->updateAll($attribute,$bedingung,$params);
// Aktualisiere die Zeilen, die die angegebene Bedingung und den(die) Primärschlüssel erfüllen
Post::model()->updateByPk($pk,$attribute,$bedingung,$params);
// Aktualisiere Zähler-Felder in den Zeilen, die die angegebene Bedingung erfüllen
Post::model()->updateCounters($zaehler,$bedingung,$params);

Hier ist $attribute ein Array von Feldwerten, die durch Feldnamen indiziert sind. $zaehler ist ein Array inkrementeller Werte, die durch Feldnamen indiziert sind. $bedingung und $params wurden bereits in vorangegangenen Abschnitten beschrieben.

6. Löschen von Datensätzen

Wir können eine Datenzeile auch löschen, wenn eine AR-Instanz mit dieser Zeile befüllt wurde.

$post=Post::model()->findByPk(10); // Unter der Annahme, es gibt einen `Post` mit ID 10
$post->delete(); // Lösche diese Zeile in der Datenbanktabelle

Beachten Sie, dass die AR-Instanz nach dem Löschen unverändert bleibt, obwohl die entsprechende Zeile in der Datenbank bereits gelöscht wurde.

Die folgenden Methoden auf Klassenebene stehen bereit, um Zeilen zu löschen, ohne sie vorher laden zu müssen:

// Lösche die Zeilen, die die angegebene Bedingung erfüllen
Post::model()->deleteAll($condition,$params);
// Lösche die Zeilen, die die angegebene Bedingung und den(die) Primärschlüssel erfüllen
Post::model()->deleteByPk($pk,$condition,$params);

7. Gültigkeitsprüfung der Daten

Wenn eine Datenzeile eingefügt oder aktualisiert wird, müssen wir oft überprüfen, ob die Werte der Felder bestimmten Regeln entsprechen. Dies ist besonders wichtig, wenn die Werte von Endbenutzern stammen. Generell sollten wir Daten, die von Clientseite stammen, niemals vertrauen.

AR führt die Gültigkeitsprüfung beim Aufruf von save() automatisch durch. Die Prüfung wird anhand der Regeln durchgeführt, die in der rules()-Methode der AR-Klasse angegeben wurden. Weitere Einzelheiten zur Definition von Prüfregeln finden Sie im Abschnitt Angeben der Regeln zur Gültigkeitsprüfung. Nachfolgend der typische Ablauf, der zum Speichern eines Datensatzes notwendig ist:

if($post->save())
{
    // Die Daten sind gültig und wurden erfolgreich eingefügt/aktualisiert
}
else
{
    // Die Daten sind ungültig. Rufen Sie getErrors() auf um die Fehlermeldungen abzufragen
}

Wenn die einzufügenden oder zu aktualisierenden Daten von einem Endbenutzer per HTML-Formular abgeschickt wurden, müssen wir diese den entsprechenden AR-Eigenschaften zuweisen. Wir können das wie folgt tun:

$post->title=$_POST['title'];
$post->content=$_POST['content'];
$post->save();

Bei vielen Feldern würden wir eine lange Liste solcher Zuweisungen benötigen. Linderung verspricht hier der Einsatz der attributes-Eigenschaft, wie unten gezeigt. Weitere Details finden Sie im Abschnitt Absichern von Attributzuweisungen sowie im Kapitel Erstellen der Action.

// Angenommen, $_POST['Post'] ist ein Array von Werten, 
// das durch Feldnamen indiziert wurde
$post->attributes=$_POST['Post'];
$post->save();

8. Vergleichen von Records

Wie Tabellenzeilen werden AR-Instanzen eindeutig durch Primärschlüsselwerte identifiziert. Um zwei AR-Instanzen zu vergleichen, müssen wir daher lediglich die Werte ihrer Primärschlüssel vergleichen, vorausgesetzt, sie gehören beide zur selben AR-Klasse. Einfacher geht dies jedoch über einen Aufruf von CActiveRecord::equals().

Info: Im Unterschied zu anderen Frameworks, unterstützen Yii’s AR zusammengesetzte Primärschlüssel. Ein zusammengesetzter Primärschlüssel besteht aus zwei oder mehr Feldern. Entsprechend wird der Primärschlüsselwert in Yii als Array dargestellt. Die Eigenschaft primaryKey liefert den Wert des Primärschlüssels einer AR-Instanz.

9. Anpassung

CActiveRecord stellt einige Platzhalter-Methoden bereit, die in abgeleiteten Klassen zur Anpassung bestimmter Abläufe überschrieben werden können.

  • beforeValidate und afterValidate: diese werden aufgerufen, bevor bzw. nachdem die Gültigkeitsprüfung durchgeführt wird/wurde.

  • beforeSave und afterSave: diese werden aufgerufen, bevor bzw. nachdem die AR-Instanz gespeichert wird/wurde.

  • beforeDelete und afterDelete: diese werden aufgerufen, bevor bzw. nachdem eine AR-Instanz gelöscht wird/wurde.

  • afterConstruct: diese wird aufgerufen, nachdem eine AR-Instanz mit dem new Operator erstellt wurde.

  • beforeFind: diese wird aufgerufen, bevor eine Abfrage (z.B. find(), findAll()) mit einem AR-Finder durchgeführt wird. Diese Methode steht seit Version 1.0.9 zur Verfügung.

  • afterFind: diese wird aufgerufen, nachdem eine AR-Instanz als Ergebnis einer Abfrage erstellt wurde.

10. Transaktionen mit AR

Jede AR-Instanz hat eine Eigenschaft mit dem Namen dbConnection, welche eine Instanz von CDbConnection darstellt. Bei Bedarf können wir deshalb beim Arbeiten mit AR das Transaktions-Feature von Yii-DAO verwenden:

$model=Post::model();
$transaction=$model->dbConnection->beginTransaction();
try
{
    // Finden und Speichern sind zwei Schritte, zwischen denen eine andere
    // Anfrage vorkommen könnte. Wir verwenden daher eine Transaktion, um 
    // Konsistenz und Integrität zu gewährleisten.
    $post=$model->findByPk(10);
    $post->title='Titel eines neuen Beitrags';
    $post->save();
    $transaction->commit();
}
catch(Exception $e)
{
    $transaction->rollBack();
}

11. Benannte Bereiche

Hinweis: Benannte Bereiche werden seit Version 1.0.5 unterstützt. Die usprüngliche Idee für benannte Bereiche stammt von Ruby on Rails.

Ein benannter Bereich (engl.: named scope) stellt ein benanntes Abfragekriterium dar, das mit anderen benannten Bereichen kombiniert und auf eine ActiveRecord-Abfrage angewendet werden kann.

Benannte Bereiche werden in der Methode CActiveRecord::scopes() hauptsächlich als Name-Kriterium-Paare definiert. Der folgende Code deklariert die beiden benannten Bereiche veroeffentlicht und kuerzlich in der Model-Klasse Beitrag:

class Beitrag extends CActiveRecord
{
    ......
    public function scopes()
    {
        return array(
            'veroeffentlicht'=>array(
                'condition'=>'status=1',
            ),
            'kuerzlich'=>array(
                'order'=>'erstellZeit DESC',
                'limit'=>5,
            ),
        );
    }
}

Jeder benannte Bereich wird als Array deklariert, das zum Initialisieren einer CDbCriteria-Instanz verwendet werden kann. Der benannte Bereich kuerzlich bestimmt zum Beispiel, dass die order-Eigenschaft auf erstellZeit DESC und die limit-Eigenschaft auf 5 gesetzt werden soll. Dies wird in ein Abfragekriterium übersetzt, das die letzten 5 Beiträge zurückliefern sollte.

Benannte Bereiche werden meist als Modifikatoren beim Aufruf von find-Methoden verwendet. Mehrere benannte Bereiche können miteinander verkettet werden und resultieren so in einem immer weiter eingeschränkten Abfrageergebnis. Um zum Beispiel die letzten veröffentlichten Beiträge zu finden, können wir diesen Code verwenden:

$beitraege=Beitrag::model()->veroeffentlicht()->kuerzlich()->findAll();

Benannte Bereiche müssen grundsätzlich links vom Aufruf einer find-Methode stehen. Jeder einzelne von ihnen stellt ein Abfragekriterium bereit, das mit anderen Kriterien kombiniert wird, inklusive demjenigen, das als Parameter and die find-Methode übergeben wurde. Letztendlich fügt man einer Abfrage also eine Liste von Filtern hinzu.

Seit Version 1.0.6 können benannte Bereiche auch mit update- und delete-Methoden verwendet werden. Der folgende Code würde zum Beispiel alle kürzlich veröffentlichten Beiträge löschen:

Beitrag::model()->veroeffentlicht()->kuerzlich()->delete();

Hinweis: Benannte Bereiche können nur mit Methoden auf Klassenebene verwendet werden. Das bedeutet, dass die Methode über KlassenName::model() aufgerufen werden muss.

Parametriesierte benannte Bereiche

Benannte Bereiche können parametrisiert werden. Wir könnten zum Beispiel die Anzahl der Beiträge des benannten Bereichs kuerzlich anpassen wollen. Statt den Bereich in der CActiveRecord::scopes-Methode anzugeben, müssen wir dazu eine neue Methode mit dem Namen des Bereichs definieren:

public function kuerzlich($limit=5)
{
    $this->getDbCriteria()->mergeWith(array(
        'order'=>'createTime DESC',
        'limit'=>$limit,
    ));
    return $this;
}

Wir können dann den folgenden Befehl verwenden, um die letzten 3 veröffentlichten Beiträge zu erhalten:

$beitraege=Beitrag::model()->veroeffentlicht()->kuerzlich(3)->findAll();

Wenn wir den Parameter 3 hier nicht angeben, würden wir standardmäßig die letzten 5 veröffentlichten Beiträge erhalten.

Standardmäßiger benannter Bereich

Ein benannter Bereich kann auch als Standardbereich für eine Modelklasse festgelegt werden, so dass er bei allen Abfragen (inkl. relationalen) verwendet wird. So könnte zum Beispiel eine mehrsprachige Website ihre Inhalte immer nur in der Sprache des aktuellen Besuchers anzeigen wollen. Da bei den Abfragen für diese Inhalten immer die selben Sprachkriterien verwendet werden sollen, können wir einen benannten Bereich als Standard festlegen, um dieses Problem zu lösen. Dazu überschreiben wir die Methode CActiveRecord::defaultScope wie folgt:

class Content extends CActiveRecord
{
    public function defaultScope()
    {
        return array(
            'condition'=>"sprache='".Yii::app()->language."'",
        );
    }
}

Dadurch verwendet der folgene Aufruf automatisch das eben festgelegte Abfragekriterium.

$contents=Content::model()->findAll();

Beachten Sie, dass der Standardbereich nur für SELECT-Abfragen verwendet wird. Bei INSERT-, UPDATE- und DELETE-Statements wird er ignoriert.