ActiveRecord
Man kann so gut wie alle Datenbankaufgaben mit Yii-DAO lösen. In 90% der Fälle führt man aber immer wieder die gleichen Anweisungen zum Lesen, Schreiben, Aktualisieren und Löschen von Datensätzen (CRUD) aus. Außerdem erschwert es die Codewartung, wenn zu viele SQL-Anweisungen darin vorkommen. Als Alternative bieten sich daher oft ActiveRecords an.
ActiveRecords (oder kurz AR) sind eine verbreitete Technik zur sog. objektrelationalen
Abbildung (engl.: object-relational mapping,ORM). Jede AR-Klasse steht für
eine Tabelle (oder einen View) in der Datenbank. Die Spalten der Tabelle
werden zu AR-Klasseneigenschaften. Eine einzelne Tabellenzeile wird zu einem
AR-Objekt, das auch gleich Methoden für die üblichen CRUD-Operationen
bereitstellt. So kann man durch AR objektorientiert mit DB-Daten arbeiten.
Um zum Beispiel eine neue Zeile in die Tabelle tbl_post
einzufügen, schreibt
man:
$post=new Post; $post->title='Beispielbeitrag'; $post->content='Inhalt des Beitrags'; $post->save();
In diesem Kapitel geht es darum, wie man AR-Instanzen anlegt und für CRUD-Operationen verwendet. Im nächsten Kapitel zeigen wir dann, wie man mit Relationen arbeitet. Sämtliche Beispiele basieren auf der folgenden Datenbanktabelle. Beachten Sie dabei bitte, dass Sie SQL AUTOINCREMENT durch AUTO_INCREMENT ersetzen müssen, falls Sie MySQL verwenden.
CREATE TABLE tbl_post ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, title VARCHAR(128) NOT NULL, content TEXT NOT NULL, create_time INTEGER NOT NULL );
Hinweis: AR ist nicht unbedingt für alle Datenbankaufgaben geeignet. AR ist zweckmäßig, um Datenbanktabellen in PHP abzubilden sowie für Abfragen, die kein komplexes SQL erfordern. In komplizierten Fällen sollte man stattdessen direkt Yii-DAO verwenden.
Aufbau einer DB-Verbindung
Um auf die Datenbank zugreifen zu können, benötigt AR eine Datenbankverbindung.
Standardmäßig erwartet AR diese in der Applikationskomponente db
. Hier ein
Beispiel, wie diese Komponente konfiguriert werden kann:
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 benötigt einige Metadaten über Tabellen, um zum Beispiel die Spalteninformationen zu ermitteln. Das Lesen und Analysieren dieser Daten braucht Zeit. Falls sich das Schema Ihrer Datenbank kaum mehr ändert, sollten Sie daher Schema-Caching aktivieren, 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:
- MySQL 4.1 oder später
- PostgreSQL 7.3 oder später
- SQLite 2 und 3
- Microsoft SQL Server 2000 oder höher
- Oracle
Falls Sie statt db
eine andere Verbindungskomponente verwenden möchten oder
Sie mit AR auf mehreren Datenbanken arbeiten, können Sie
CActiveRecord::getDbConnection() in Ihrer Klasse überschreiben.
Die CActiveRecord-Klasse ist die Basisklasse für alle AR-Klassen.
Tipp: Es gibt zwei Methoden, um mit AR auf mehren Datenbanken zu arbeiten. Falls die Datenbankschemata sich unterscheiden, können Sie mehrere AR-Basisklassen anlegen, die jeweils getDbConnection() überschreiben. Ist das Schema überall gleich, ist es günstiger, die statische Variable CActiveRecord::db dynamisch zu ändern.
Definieren von AR-Klassen
Um auf eine Datenbanktabelle zuzugreifen, muss zuerst eine neue AR-Klasse
von CActiveRecord abgeleitet werden. Jede Klasse repräsentiert
eine einzelne Datenbanktabelle, eine AR-Instanz eine Zeile in dieser Tabelle.
Das folgende Beispiel zeigt den Minimalcode einer AR-Klasse. In diesem Fall
für die Tabelle tbl_post
.
class Post extends CActiveRecord { public static function model($className=__CLASS__) { return parent::model($className); } }
Tipp: Da AR-Klassen oft an vielen Stellen verwendet werden, importiert man am besten gleich das ganze Modelverzeichnis. Liegen alle AR-Klassen (wie meist üblich) im Verzeichnis
protected/models
, wird dies wie folgt konfiguriert:return array( 'import'=>array( 'application.models.*', ), );
Standardmäßig hat die AR-Klasse den gleichen Namen wie die Datenbanktabelle, Sie können aber auch einen abweichenden Tabellennamen verwenden, indem Sie die tableName()-Methode überschreiben. Die model()-Methode muss in jeder AR-Klasse definiert werden, worauf wir in Kürze noch näher eingehen werden.
Info: Um ein Tabellenpräfix zu verwenden, kann man die tableName()-Methode auch wie folgt überschreiben:
public function tableName() { return '{{post}}'; }Statt eines vollständigen Tabellennamens, gibt man den Namen der Tabelle ohne Präfix, aber dafür in doppelten geschweiften Klammern zurück.
Über die Objekteigenschaften kann man auf die Daten einer Tabellenzeile
zugreifen. Um zum Beispiel den Wert für die Spalte title
zu setzen,
schreibt man:
$post=new Post; $post->title='Ein Beispielbeitrag';
Erstaunlicherweise kann man auf die title
-Eigenschaft zugreifen, obwohl
diese in der Post
-Klasse gar nicht deklariert wurde. Das liegt daran,
das AR die magische PHP-Methode __get()
(bzw. __set()
) verwendet, um
Tabellenspalten wie Objekteigenschaften verfügbar zu machen. Versucht man
jedoch, ein nicht existentes Feld anzusprechen, wird eine Exception ausgelöst.
Info: In diesem Handbuch werden alle Tabellen- und Spaltennamen kleingeschrieben, da verschiedene DBMS mit Groß-/Kleinschreibung unterschiedlich umgehen. PostgreSQL zum Beispiel ignoriert die Schreibweise standardmäßig. Falls ein Spaltenname Groß- und Kleinbuchstaben enthält, muss er dort in Anführungszeichen gesetzt werden. Durch konsequente Kleinschreibung umgeht man dieses Problem.
AR erwartet, dass für alle Tabellen korrekte Primärschlüssel in der Datenbank
definiert wurden. Ist das für eine Tabelle nicht der Fall, muss die Methode
primaryKey()
den Primärschlüssel wie folgt zurückliefern:
public function primaryKey() { return 'id'; // Für zusammengesetzte Primärschlüssel kann ein Array wie folgt // zurückgegeben werden: // return array('pk1', 'pk2'); }
Einfügen von Datensätzen
Um eine neue Zeile in eine Datenbanktabelle einzufügen, erzeugt man eine Objektinstanz der zugehörigen AR-Klasse, setzt die entsprechenden Eigenschaften und ruft die save()-Methode auf.
$post=new Post; $post->title='Beispielbeitrag'; $post->content='Inhalt des Beispielbeitrags'; $post->create_time=time(); $post->save();
Ist in der Datenbank AUTOINCREMENT für den Primärschlüssel aktiviert, enthält
die neue AR-Instanz nach dem Speichern automatisch den vergebenen
Schlüssel. Im Beispiel enhält also das id
-Attribut den neuen Schlüssel, ohne
dass dieses explizit gesetzt wurde.
Wurden im Tabellenschema der DB statische Vorgabewerte für bestimmte Spalten definiert (z.B. ein String oder eine Zahl), werden diese nach dem Speichern ebenfalls automatisch bei den entsprechenden Eigenschaften gesetzt. Möchte man diese Vorgabewerte ändern, kann man das in der AR-Klasse wie folgt erreichen:
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
Man kann 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, schreibt man:
$post=new Post; $post->create_time=new CDbExpression('NOW()'); // $post->create_time='NOW()'; funktioniert nicht, // da 'NOW()' wie ein String behandelt werden würde. $post->save();
Tipp: Obwohl man durch AR keine umständlichen SQL-Ausdrücke mehr schreiben muss, kann es zur Fehlersuche nützlich sein, die im Hintergrund verwendeten SQL-Befehle zu untersuchen. Das geht mit Hilfe des Log-Features von Yii. Konfiguriert man zum Beispiel eine CWebLogRoute, werden die ausgeführten SQL-Befehle am Ende der Seite angezeigt. Setzt man CDbConnection::enableParamLogging auf
true
, werden dort auch die gebundenen Parameterwerte angezeigt.
Lesen von Datensätzen
Um Daten aus der Datenbanktabelle zu lesen verwendet man eine der folgenden
find
-Methoden:
// 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 wird die find
-Methode auf Post::model()
aufgerufen. Wie Sie sich
erinnern, ist die statische model()
-Methode bei jeder AR-Klasse nötig.
Sie gibt eine AR-Instanz zurück, mit der man auf Methoden der Klassenebene
zugreifen kann. Das ist ganz ähnlich zu statischen Klassenmethoden, allerdings
hier in einem Objektkontext.
Findet die find
-Methode eine Zeile zu den gegebenen Abfragebedingungen,
liefert sie ein Post
-Objekt mit den entsprechenden Daten zurück. Die
geladenen Werte können dann wie normale Objekteigenschaften z.B. mit
$post->title
ausgelesen werden.
Wurde keine entsprechende Zeile gefunden, liefert find
den Wert null zurück.
Die Abfragebedingungen werden über die Argumente $condition
und $params
an
find
übergeben. $condition
kann ein String sein, der die
WHERE
-Klausel in einer SQL Abfrage darstellt, $params
ein Array mit
Parametern, falls $condition
Platzhalter enthält. Hier ein 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. Bei PostgreSQL, muss$condition
zum Beispiel"postID"=:postID
lauten, da PostgreSQL standardmäßig die Groß-/Kleinschreibung von Spaltennamen nicht berücksichtigt.
$condition
kann auch viel komplexere Abfragebedingungen enthalten, indem man
statt eines Strings eine Instanz von CDbCriteria übergibt. Damit können dann
weitere Kriterien angegeben werden:
$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 das $params
-Argument nicht mehr benötigt wird,
da die Parameter bereits in CDbCriteria angegeben werden können.
Alternativ zu einem CDbCriteria-Objekt, kann auch ein Array an die
find
-Methode übergeben werden. Die Schlüssel und Werte des Array entsprechen
dann 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: Soll nach bestimmten Spaltenwerten in einer Tabelle gesucht werden, kann man dazu findByAttributes() verwenden.
$attributes
ist ein Array mit Spaltennamen als Schlüsseln und den gesuchten Werten als Arraywerten. In einigen Frameworks wird dies über Methoden wie z.B.findByNameAndTitle
gelöst. Obwohl diese Herangehensweise ihre Reize besitzt, sorgt sie oft für Verwirrung und Konflikte bzw. Problemen im Zusammenhang mit der Groß-/Kleinschreibung von Spaltennamen.
Erfüllen mehrere Datenzeilen die Abfragebedingung, können diese alle auf
einmal mit den folgenden findAll
-Methoden bezogen werden. Jede von Ihnen hat
ihr Pendant bei den eben beschriebenen find
-Methoden:
// 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);
Im Unterschied zu find
liefern die findAll
-Methoden ein leeres Array
zurück, falls keine entsprechende Zeile gefunden wurde.
AR bietet noch weitere Methoden, die viele gängige Aufgaben vereinfachen:
// 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);
Aktualisieren von Datensätzen
Wurde eine AR-Instanz mit den Werten einer Tabellenzeile befüllt, können diese verändert und in die Datenbank zurückgespeichert werden.
$post=Post::model()->findByPk(10); $post->title='Geänderter Titel eines Beitrags'; $post->save(); // Änderung in der Datenbank speichern
Wie Sie sehen, wird die save()-Methode auch zum
Aktualisieren von Einträgen verwendet. Wurde eine Instanz also mit new
erzeugt, fügt save() einen neuen Datensatz ein. Stammt
das Objekt von einer Abfrage, aktualisiert save() die
entsprechende Tabellenzeile. Mit CActiveRecord::isNewRecord kann man prüfen,
ob es sich um ein neues Objekt handelt oder nicht.
Man kann einzelne oder mehrere Zeilen in einer Tabelle auch aktualisieren, ohne sie vorher zu laden.AR bietet dazu die folgenden nützlichen Methoden auf Klassenebene an:
// Aktualisiere die Zeilen, die die angegebene Bedingung erfüllen Post::model()->updateAll($attribute,$bedingung,$params); // Aktualisiere die Zeilen mit dem/den angegebenen Primärschlüssel(n), // die die angegebene Bedingung erfüllen Post::model()->updateByPk($pk,$attribute,$bedingung,$params); // Aktualisiere Zählerspalten in den Zeilen, die die angegebene Bedingung erfüllen Post::model()->updateCounters($zaehler,$bedingung,$params);
Hier ist $attribute
ein Array von Werten, die durch Feldnamen indiziert sind.
$zaehler
ist ein Array ansteigender Werte, die durch Feldnamen indiziert
sind. $bedingung
und $params
wurden bereits in den vorangegangenen Abschnitten
beschrieben.
Löschen von Datensätzen
Man kann eine Datenzeile auch löschen, wenn die AR-Instanz dieser Zeile entspricht:
$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, auch wenn die entsprechende Zeile in der Datenbank bereits gelöscht wurde.
Mit diesen Methoden (wieder auf Klassenebene) kann man Zeilen auch 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 mit den angegebenen Primärschlüsseln, // die die angegebene Bedingung erfüllen Post::model()->deleteByPk($pk,$condition,$params);
Validieren der Daten
Vor dem Einfügen oder Aktualisieren eines Datensatzes, muss oftmals geprüft
werden, ob die Werte auch bestimmten Regeln entsprechen. Diesen Vorgang nennt
man auch Validierung
. Sie ist insbesondere wichtig, wenn die zu speichernden
Werte von Endanwendern stammen. Sämtlichen Daten von der Clientseite sollte man
grundsätzlich nie vertrauen.
AR führt die Validierung beim Aufruf von save() automatisch durch. Die Prüfung erfolgt anhand der Regeln, die in der rules()-Methode der AR-Klasse angegeben wurden. Weitere Einzelheiten zur Definition von Prüfregeln finden Sie im Abschnitt Angeben von Validierungsregeln. Beim Speichern kommt es in der Regel zu diesem typischen Ablauf:
if($post->save()) { // Die Daten sind gültig und wurden erfolgreich eingefügt/aktualisiert } else { // Die Daten sind ungültig. Fehlermeldungen mit getErrors() abfragen }
Stammen die einzufügenden oder zu aktualisierenden Daten von einem HTML-Formular, müssen diese den entsprechenden AR-Eigenschaften zugewiesen werden:
$post->title=$_POST['title']; $post->content=$_POST['content']; $post->save();
Hat eine Tabelle viele Spalten, müsste man also umständlich alle Felder einzeln zuweisen. Über die attributes-Eigenschaft kann man das vermeiden, wie im folgenden Beispiel zu sehen. Weitere Details hierzu finden Sie im Abschnitt Sichere 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();
Vergleichen von Records
Auch AR-Instanzen werden wie die entsprechenden Tabellenzeilen eindeutig durch ihre Primärschlüsselwerte identifiziert. Man kann zwei Instanzen also einfach über deren Primärschlüssel vergleichen, vorausgesetzt, sie gehören zur selben Klasse. Einfacher geht dies jedoch mit CActiveRecord::equals().
Info: Im Unterschied zu anderen Frameworks unterstützen Yiis AR auch zusammengesetzte Primärschlüssel. Sie bestehen aus zwei oder mehr Feldern und werden daher als Array dargestellt. Die Eigenschaft primaryKey liefert den Wert des Primärschlüssels einer AR-Instanz.
Anpassung
Zur Anpassung an bestimmte Abläufe, sind in CActiveRecord einige Methoden als Platzhalter implementiert, die man in eigenen AR-Klassen einfach überschreiben kann.
beforeValidate und afterValidate: werden vor bzw. nach der Validierung aufgerufen
beforeSave und afterSave: werden vor bzw. nach dem Speichern aufgerufen
beforeDelete und afterDelete: werden vor bzw. nach dem Löschen einer AR-Instanz aufgerufen
afterConstruct: wird nach dem Erzeugen einer neuen Instanz aufgerufen
beforeFind: werden vor einer Suchabfrage (z.B.
find()
,findAll()
) ausgeführt.afterFind: wird aufgerufen, nachdem eine Instanz aus einem Suchergebnis erzeugt wurde.
Transaktionen mit AR
Über die dbConnection-Eigenschaft kann bei jeder AR-Instanz auf die zugrundeliegende CDbConnection zugegriffen werden. Bei Bedarf kann man so 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(); }
Scopes
Hinweis: Die Idee für Scopes stammt ursprünglich von Ruby on Rails.
Ein Scope (engl.: named scope, sinngem.: benannter Bereich) stellt ein vordefiniertes Abfragekriterium dar, das man bei einem AR unter einem bestimmten Namen abrufen und sogar mit anderen Scopes kombinieren kann.
Meist werden Scopes als Array von Name-Kriterium-Paaren in der Methode
CActiveRecord::scopes() definiert. Der folgende Code deklariert
zum Beispiel die beiden Scopes veroeffentlicht
und kuerzlich
in der
Modelklasse Beitrag
:
class Beitrag extends CActiveRecord { ...... public function scopes() { return array( 'veroeffentlicht'=>array( 'condition'=>'status=1', ), 'kuerzlich'=>array( 'order'=>'erstellZeit DESC', 'limit'=>5, ), ); } }
Jeder Scope besteht aus einem Array, dessen Werte zum Initialisieren
einer CDbCriteria-Instanz verwendet werden können. Der Scope
kuerzlich
bestimmt zum Beispiel, dass die order
-Eigenschaft auf
erstell_zeit DESC
und die limit
-Eigenschaft auf 5 gesetzt werden soll. Dies
wird also in ein Abfragekriterium übersetzt, das die letzten 5 Beiträge
zurückliefern sollte.
Scopes werden meist als Modifikatoren beim Aufruf von find
-Methoden
verwendet. Mehrere Scopes können miteinander verkettet werden
und resultieren so in einem immer weiter eingeschränkten Abfrageergebnis.
Mit dem folgenden Code kann man so zum Beispiel die letzten 5 veröffentlichten
Beiträge abfragen:
$beitraege=Beitrag::model()->veroeffentlicht()->kuerzlich()->findAll();
Scopes müssen grundsätzlich links vom Aufruf einer
find
-Methode stehen. Jeder einzelne von ihnen liefert ein Abfragekriterium, das
mit weiteren 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.
Hinweis: Scopes können nur mit Methoden auf Klassenebene verwendet werden. Das bedeutet, dass die Methoden über
KlassenName::model()
aufgerufen werden muss.
Parametrisierte Scopes
Scopes können auch parametrisiert werden. Man könnte zum Beispiel
die Anzahl der Beiträge des Scopes kuerzlich
anpassen.
Statt den Scope in der CActiveRecord::scopes-Methode anzugeben, wird
dazu eine eigene Methode mit dem Namen des Scopes verwendet:
public function kuerzlich($limit=5) { $this->getDbCriteria()->mergeWith(array( 'order'=>'create_time DESC', 'limit'=>$limit, )); return $this; }
Die letzten 3 veröffentlichten Beiträge kann man dann so abfragen:
$beitraege=Beitrag::model()->veroeffentlicht()->kuerzlich(3)->findAll();
Wird der Parameter 3 weggelassen, werden standardmäßig die letzten 5 Beiträge angezeigt.
Standardscope
Ein Scope kann auch als Standardscope 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 dazu bei den allen Abfragen immer die selben Sprachkriterien verwendet werden müssen, kann man diese Aufgabe mit einem Standardscope lösen. Dazu wird die Methode CActiveRecord::defaultScope wie folgt überschrieben:
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();
Hinweis: Der Standardscope wird nur für
SELECT
-Abfragen verwendet. BeiINSERT
-,UPDATE
- undDELETE
-Statements wird er ignoriert. Innerhalb einer Scopedeklaration können außerdem keine DB-Abfragen auf die gleiche AR-Klasse durchgeführt werden.