0 follower

Wzorzec Rekordu Aktywnego (ang. Active Record)

Chociaż Yii DAO może uporać się z wirtualnymi oraz bazodanowymi zadaniami, istnieje szansa, że będziemy spędzać 90% naszego czasu pisząc wyrażenia SQL, które wykonują operacje CRUD (create - tworzenie, read - czytanie, update - aktualizowanie oraz delete - usuwanie). Trudno również jest zarządzać kodem, który jest pomieszany z wyrażeniami SQL. Do rozwiązania tych problemów możemy użyć wzorca Rekordu Aktywnego (ang. Active Record).

Aktywny Rekord (AR) jest popularną techniką mapowania obiektowo-relacyjnego. Każda klasa AR reprezentuje tabelę bazy danych (lub widok), których atrybuty reprezentowane są poprzez atrybuty klasy AR a instancja AR reprezentuje wiersz w tej tabeli. Wspólne operacje CRUD są zaimplementowane jako metody AR. W rezultacie, posiadamy dostęp do naszych danych w bardziej obiektowo zorientowany sposób. Na przykład: możemy użyć poniższego kodu aby wstawić nowy wiersz do tabeli tbl_ost:

$post=new Post;
$post->title='przykładowy post';
$post->content='zawartość postu';
$post->save();

W dalszej części opiszemy jak utworzyć AR i użyć go do wykonywania operacji CRUD. W następnej sekcji pokażemy jak używać AR by radzić sobie z relacjami w bazach danych. Dla uproszczeniami używamy w przykładach tej sekcji następującej tabeli bazy danych. Zauważ, że jeśli używasz bazy danych MySQL, powinieneś zamienić AUTOINCREMENT na AUTO_INCREMENT w poniższym kodzie SQL.

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
);

Wskazówka: AR nie został pomyślany do rozwiązywania wszystkich zadań związanych z bazą danych. Najlepiej używać go do modelowania tabel baz danych w konstrukcjach PHP oraz wykonywania zapytań, które nie zawierają skomplikowanego kodu SQL. Dla tych skomplikowanych scenariuszy powinno używać się Yii DAO.

1. Ustanawianie połączeń DB

AR jest zależy od połączenia DB gdy wykonuje operacje zależne od DB. Domyślnie, zakłada, że komponent aplikacji db dostarcza wymaganej instancji CDbConnection która reprezentuje połączenie z bazą danych. Poniżej znajduje się przykładowa konfiguracja aplikacji

return array(
    'components'=>array(
        'db'=>array(
            'class'=>'system.db.CDbConnection',
            'connectionString'=>'sqlite:path/to/dbfile',
            // włączenie cache'owania schematu celem zwiększenia wydajności
            // 'schemaCachingDuration'=>3600,
        ),
    ),
);

Wskazówka: Ponieważ Rekord Aktywny zależy od metadanych tabeli zawierających informacje o kolumnach, zajmuje mu to nieco czasu, aby je odczytać oraz zanalizować. Jeśli prawdopodobieństwo, że schemat twojej bazy danych jest małe, powinieneś włączyć cache'owanie schematu bazy danych poprzez skonfigurowanie właściwości CDbConnection::schemaCachingDuration poprzez przypisanie jej wartości większej niż 0.

Wsparcie dla AR jest ograniczone przez DBMS. Aktualnie, tylko następujące DBMS są wspierane:

Jeśli chcesz używać komponentu aplikacji innego niż db lub jeśli chcesz pracować z wieloma bazami danych używając AR, powinieneś nadpisać metodę CActiveRecord::getDbConnection(). Klasa CActiveRecord jest klasą bazową dla wszystkich klas AR.

Wskazówka: Istnieją dwa sposoby pracowania z wieloma bazami danych z użyciem AR. Jeśli schematy bazy danych różnią się, możesz utworzyć różne bazowe klasy AR z różniącymi się implementacjami metody getDbConnection(). W przeciwnym przypadku, lepszym pomysłem jest dynamiczna zmiana statycznej zmiennej CActiveRecord::db.

2. Definiowanie klasy AR

Aby uzyskać dostęp do tabeli bazy danych musimy najpierw zdefiniować klasę AR poprzez rozszerzenie CActiveRecord. Każda klasa AR reprezentuje jedną tabele bazy danych a jedna instancja reprezentuje wiersz tej tabeli. Następujący przykład pokazuje minimalny kod potrzebny aby klasa AR reprezentowała tabelę tbl_ost.

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

Wskazówka: Ponieważ klasy AR są często używane w wielu różnych miejscach, możemy zaimportować zawartość folderu zawierającego klasy AR zamiast dołączać je jedna po drugiej. Na przykład, jeśli wszystkie nasze pliki zawierające klasy AR znajdują się w katalogu protected/models, możemy skonfigurować aplikację w następujący sposób:

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

Domyślnie, nazwa klasy AR jest identyczna z nazwą tabeli w bazie danych. Jeśli nazwa klasy różni się, nadpisz metodę tableName(). Metoda model() jest zadeklarowana jako taka dla każdej klasy AR (wyjaśnienie tego nastąpi później).

Info: Aby móc używać prefiksów tablic metoda tableName() dla klasy AR może być nadpisana następująco,

public function tableName()
{
    return '{{post}}';
}

Oznacza to, że zamiast zwracać pełną i dokładną nazwę tabeli, zwracamy jej nazwę bez prefiksu, dodatkowo zamkniętą w podwójnych nawiasach klamrowych.

Wartości kolumn wiersza tabeli są dostępne jako właściwości odpowiednich instancji klasy AR. Na przykład, następujący kod ustawia kolumnę (atrybut) title:

$post=new Post;
$post->title='przykładowy post';

Chociaż nigdy bezpośrednio nie zdeklarowaliśmy właściwości title w klasie tbl_ost, jest ona dostępna w powyższym kodzie. Dzieje się tak, ponieważ title jest kolumną w tabeli tbl_ost a CActiveRecord czyni ją dostępną poprzez właściwość przy pomocy magicznej metody PHP __get(). Jeśli w ten sam sposób spróbujemy uzyskać dostęp do nieistniejącej kolumny wyjątek zostanie rzucony.

Info: W tym poradniku nazywamy kolumny przy użyciu notacji wielbłąda (np. createTime). Czynimy tak, ze względu na to, że kolumny dostępne są w taki sam sposób jak zwykłe właściwości obiektu, które również używają notacji wielbłąda. Chociaż, używanie notacji wielbłąda czyni nasz kod PHP bardziej konsekwentnym w nazewnictwie, może to powodować problemy związane z wielkością liter w pewnych DBMS. Na przykład, PostgreSQL traktuje domyślnie nazwy kolumn jako niezależne od wielkości liter i dlatego musimy używać nazwy kolumn podanej w cudzysłowiu w warunkach zapytania jeśli kolumna zawiera pomieszane duże i małe litery. Z tego powodu, mądrą decyzją jest nazywanie kolumn (a także tabel) jedynie przy użyciu małych liter (np. create_time) w celu uniknięcia potencjalnych problemów z wielkością liter.

public function primaryKey()
{
    return 'id';
    // Dla złożonych kluczy głównych, zwróć następująca tablicę
    // return array('pk1', 'pk2');
}

3. Tworzenie rekordu

Aby wstawić nowy wiersz do tabeli bazy danych, tworzymy nową instancję odpowiedniej klasy AR, ustawiamy jej właściwości powiązane z kolumnami tabel i wołamy metodę save() aby zakończyć wstawianie.

$post=new Post;
$post->title='przykładowy post';
$post->content='zawartość przykładowego postu';
$post->create_time=time();
$post->save();

Jeśli klucz główny tabeli jest autoinkrementowalny, po wstawieniu, instancja będzie zawierała zaktualizowaną wartość klucza głównego. w powyższym przykładzie właściwość id odpowiada wartości klucza głównego nowo wstawionego postu, mimo że nigdy nie zmienialiśmy tej wartości bezpośrednio.

Jeśli kolumna została zdefiniowana wraz z jakąś statyczną, domyślną wartością (np. łańcuch znaków, liczba) w schemacie tabeli bazy danych, odpowiadająca jej własność w instancji AR będzie automatycznie posiadała tą wartość, gdy instancja zostanie utworzona. Jednym ze sposobów zmiany tej wartości domyślnej jest bezpośrednie zdeklarowanie właściwości w klasie AR:

class Post extends CActiveRecord
{
    public $title='proszę wprowadź tytuł';
    ......
}
 
$post=new Post;
echo $post->title;  // to wyświetli tekst: proszę wprowadź tytuł

Atrybut może mieć przypisaną wartość typu CDbExpression zanim rekord zostanie zapisany (zarówno podczas wstawiania jak i aktualizacji) do bazy danych. Na przykład, w celu zapisania stempla czasu (ang. timestamp) zwracanego przez funkcję MYSQL NOW(), możemy użyć następującego kodu:

$post=new Post;
$post->create_time=new CDbExpression('NOW()');
// $post->create_time='NOW()'; nie zadziała gdyż 
// 'NOW()' będzie potraktowany jako łańcuch znaków
$post->save();

Wskazówka: Chociaż AR umożliwia wykonywanie operacji na bazie danych pez potrzeby pisania uciążliwych zapytań SQL, często chcemy wiedzieć jakie zapytanie SQL jest wykonywane w tle przez AR. Możemy uzyskać tą informację poprzez włączenie w Yii funkcjonalności logowania. Na przykład, możemy włączyć CWebLogRoute w konfiguracji aplikacji, dzięki czemu bedziemy widzieć wykonywane zapytania SQL na końcu każdej strony. Możemy ustawić właściwość CDbConnection::enableParamLogging jako true w konfiguracji aplikacji, tak, że wartości parametrów powiązanych z instrukcją SQL będą również logowane.

4. Odczytywanie rekordu

Aby odczytać dane z tabeli bazodanowej wołany jedną z następujących metod find:

// znajduje pierwszy wiersz spełniający określone warunki
$post=Post::model()->find($condition,$params);
// znajduje wiersz o konkretnym kluczu głównym
$post=Post::model()->findByPk($postID,$condition,$params);
// znajduje wiersz o określonych wartościach atrybutów
$post=Post::model()->findByAttributes($attributes,$condition,$params);
// znajduje pierwszy wiersz używając określonego wyrażenia SQL
$post=Post::model()->findBySql($sql,$params);

Powyżej, wywołujemy metodę find wraz z Post::model(). Pamiętaj, że ta statyczna metoda model() jest wymagana dla każdej klasy AR. Metoda ta zwraca instancję A, która jest używana by otrzymać dostęp do metod na poziomie klasy w kontekście obiektu (coś podobnego do statycznych metod klas).

Jeśli metoda find znajdzie wiersz spełniający warunki zapytania, zwróci ona instancję tbl_ost, której właściwości będą zawierać odpowiadające kolumnom wartości wiersza tabeli. Możemy wtedy czytać załadowane wartości tak jak to robimy w przypadku właściwości obiektu, na przykład, echo $post->title;.

Metoda find zwróci wartość null, jeśli nie znajdzie niczego w bazie danych, co spełniałoby dane warunki zapytania.

Podczas wywoływania metody find używamy $condition (warunków) oraz $params (parametrów) aby określić warunki zapytania. Tutaj $condition może być ciągiem znaków reprezentujących klauzulę WHERE w wyrażeniu SQL a $params jest tablicą parametrów, których wartości powinny być przypięte do placeholderów w $condition. Na przykład:

// znajdź wiersz z postID=10
$post=Post::model()->find('postID=:postID', array(':postID'=>10));

Uwaga: W powyższym przykładzie będziemy musieli unikać referencji do kolumny postID dla pewnych DBMS. Na przykład, jesli używamy PostrgreSQL, będziemy musieli zapisać warunek jako "postID"=:postID, ze względu na to, że PostgreSQL domyślnie rozróżnia wielkość liter kolumn.

Możemy również używać $condition do zdefiniowania bardziej rozbudowanych warunków zapytań. Zamiast łańcuchem znaków, $condition może być instancją CDbCriteria, która pozwala na określenie warunków innych niż klauzula WHERE. Na przykład:

$criteria=new CDbCriteria;
$criteria->select='title';  // wybierz tylko kolumnę 'title' 
$criteria->condition='postID=:postID';
$criteria->params=array(':postID'=>10);
$post=Post::model()->find($criteria); // $params nie jest wymagane

Zauważ, że kiedy używamy CDbCriteria jako warunków zapytania, wartość parametru $params jest niepotrzebna, gdyż może być ona zdefiniowana w CDbCriteria, tak jak pokazano powyżej.

Alternatywnym sposobem do CDbCriteria jest przekazanie tablicy do metody find. Klucze i wartości tablicy odpowiadają nazwom i wartościom właściwości kryteriów. Powyższy przykład może zostać przepisany w następujący sposób:

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

Info: Kiedy warunki zapytania polegają ma porównywaniu kolumn z określonymi wartościami, możemy użyć findByAttributes(). Parametrami $attributes zostaje wtedy tablica wartości indeksowana poprzez nazwy kolumn. W części frameworków, to zadanie może zostać zrealizowane poprzez wywołanie metod podobnych do findByNameAndTitle. Chociaż to podejście wygląda bardzo atrakcyjnie często powoduje zamieszanie, konflikty oraz problemy np. z czułością na wielkość liter w nazwach kolumn.

Kiedy więcej wierszy danych pasuje do określonych warunków zapytania, możemy dostarczyć je wszystkie razem używając następujących metod findAll, z których każda ma swój odpowiednik w metodzie find, tak jak było to wcześniej opisane.

// znajduje wszystkie wiersze spełniające określone warunki
$posts=Post::model()->findAll($condition,$params);
// znajduje wszystkie wiersze o konkretnym kluczu głównym
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
// znajduje wiersze o określonych wartościach atrybutów
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
// znajduje wiersze używając określonego wyrażenia SQL
$posts=Post::model()->findAllBySql($sql,$params);

Jeśli nic nie pasuje do warunków zapytania, findAll zwróci pustą tablicę. Różni się tym od metody find, która zwróci wartość null jeśli nic nie zostało znalezione.

Poza opisanymi powyżej metodami find and findAll, dla wygody dostarczono następujących metod:

// zwraca ilość wierszy spełniających określone warunki
$n=Post::model()->count($condition,$params);
// zwraca ilość wierszy używanych w określonym wyrażeniu SQL
$n=Post::model()->countBySql($sql,$params);
// sprawdza czy istnieje przynajmniej jeden wiersz spełniający określone warunki
$exists=Post::model()->exists($condition,$params);

5. Aktualizowanie rekordu

Po tym jak instancja AR została wypełniona wartościami kolumn, możemy zmienić je i zapisać je z powrotem w tabeli bazodanowej.

$post=Post::model()->findByPk(10);
$post->title='nowy tytuł postu';
$post->save(); // zapisz zmiany do bazy danych

Jak widać, używamy tej samej metody save() do wykonania operacji wstawiania jak i aktualizowania. Jeśli instancja AR została utworzona za pomocą operatora new, wywołanie save() spowoduje wstawienie nowego wiersza do tabeli bazy danych; jeśli instancja AR jest rezultatem wywołania metody find lub findAll, wywołanie save() spowoduje zaktualizowanie istniejącego wiersza w tabeli. Oczywiście, możemy użyć CActiveRecord::isNewRecord aby powiedzieć czy instancja AR jest nowa czy też nie.

Istnieje również możliwość aktualizacji jednego lub więcej wiersz w tabeli bazy danych bez konieczności ich wcześniejszego wczytywania. AR dostarcza w tym celu następujących, pomocnych metod na poziomie klasy:

// aktualizuje wiersze spełniający określone warunki
Post::model()->updateAll($attributes,$condition,$params);
// aktualizuje wiersze pasujące do określonych warunki oraz klucza(y) głównego(ych)
Post::model()->updateByPk($pk,$attributes,$condition,$params);
// aktualizuje licznik kolumn w wierszach spełniających określone warunki
Post::model()->updateCounters($counters,$condition,$params);

W powyższych przykładach, $attributes jest tablicą wartości kolumn indeksowanych przez nazwy kolumn; $counters jest tablicą zwiększających się wartości indeksowanych przez nazwy kolumn; $condition oraz $params są opisane w poprzedniej sekcji.

6. Usuwanie rekordu

Możemy również usunąć wiersz danych jeśli instancja AR została wypełniona tym wierszem.

$post=Post::model()->findByPk(10); // zakładamy, że istnieje post, którego ID wynosi 10
$post->delete(); // usuń wiersz danych z tabeli bazy danych

Zauważ, że po usunięciu, instancja AR pozostaje niezmieniona, ale odpowiadający jej wiersz w tabeli bazodanowej już nie istnieje.

Następujące metody klasowe zostały dostarczone aby móc usuwać wiersze bez konieczności ich wcześniejszego wczytywania:

// usuń wiersze spełniające określone warunki
Post::model()->deleteAll($condition,$params);
// usuń wiersze pasujące do określonych warunków oraz klucza(y) głównego(ych)
Post::model()->deleteByPk($pk,$condition,$params);

7. Walidacja danych

Często podczas wstawiania lub aktualizowania wiersza mamy potrzebę sprawdzić czy wartości kolumny spełniają pewne warunki. Jest to szczególnie ważne, jeśli wartości kolumn dostarczane są przez użytkowników końcowych. Uogólniające, nigdy nie powinniśmy ufać niczemu przychodzącemu od strony klienta.

AR automatycznie dokonuje walidacji podczas wywoływania metody save(). Walidacja bazuje na regułach określonych w metodzie rules() klasy AR. Aby uzyskać więcej szczegółów jak określać reguły walidacji, zobacz sekcję
Deklarowanie reguł walidacji. Poniżej znajduje się typowy przepływ podczas zapisywania rekordu.

if($post->save())
{
  // dane są poprawne oraz zostały szczęśliwie zapisane/zaktualizowane  
}
else
{
  // dane są niepoprawne. Wywołaj getErrors() aby otrzymać komunikaty błędów
}

Kiedy dane używane do wstawiania lub aktualizowania są dostarczane przez użytkownika końcowego za pomocą formularza HTML, potrzebujemy przypisać je do odpowiadających im właściwości AR. Możemy to zrobić następująco:

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

Jeśli mamy wiele kolumn, będziemy widzieli długą listę takich przypisań. Można to zmniejszyć poprzez używanie właściwości attributes w sposób jaki pokazano poniżej. Więcej szczegółów można znaleźć w sekcji Zabezpieczaniu przypisań atrybutów oraz sekcji Tworzeniu akcji.

// zakładamy, że $_POST['Post'] jest tablicą wartości kolumn indeksowanych przez 
// nazwy kolumn
$post->attributes=$_POST['Post'];
$post->save();

8. Porównywanie rekordów

Tak jak wiersze tabel, instancje AR są jednoznacznie identyfikowane przez ich wartości kluczy głównych. Dlatego też, porównując dwie instancje AR, musimy porównać jedynie ich wartości kluczy głównych, zakładając, że należą do tej samej klasy AR. Jednakże najprostszym sposobem jest wywołanie CActiveRecord::equals().

Info: W odróżnieniu do implementacji AR w innych frameworkach, Yii wspiera klucze złożone w AR. Klucze złożone zawierają więcej niż jedną kolumnę. Odpowiednio, wartości kluczy głównych reprezentowane są w Yii pod postacią tablicy. Właściwość primaryKey zawiera wartość klucza głównego instancji AR.

9. Dostosowywanie (do własnych potrzeb)

CActiveRecord dostarcza kilku metod "wypełniaczy", które mogą być nadpisane w klasach potomnych aby dostosować ich sterowanie kolejnością zadań (ang. workflow).

  • beforeValidate oraz afterValidate: są wywoływane przed (ang. before) i po (ang. after) walidacji.

  • beforeSave oraz afterSave: są wywoływane przed i po zapisie instancji AR.

  • beforeDelete oraz afterDelete: są wywoływane przed i po usunięciu instancji AR.

  • afterConstruct: jest wywoływana dla każdej instancji AR utworzonej za pomocą operatora new.

  • beforeFind: jest wywoływana zanim instancja AR zostanie użyta do wykonania zapytania (np. find(), findAll()).

  • afterFind: jest wywoływana dla każdej instancji AR utworzonej jako rezultat zapytania.

10. Używanie transakcji w AR

Każda instancja AR zawiera właściwość nazwaną dbConnection która jest instancją CDbConnection. Możemy wtedy używać funkcjonalności transakcji dostarczanej przez Yii DAO jeśli występuje taka potrzeba podczas pracy z AR:

$model=Post::model();
$transaction=$model->dbConnection->beginTransaction();
try
{
    // szukanie i zapisywanie są dwoma krokami, które mogą być przychodzić za pomocą 
    // innych żądań, dlatego też używamy transakcji aby być pewnymi logiki oraz spójności danych
    $post=$model->findByPk(10);
    $post->title='nowy tytuł postu';
    $post->save();
    $transaction->commit();
}
catch(Exception $e)
{
    $transaction->rollBack();
}

11. Nazwane podzbiory (ang. Named Scopes)

Uwaga: Pierwotny pomysł na nazwane podzbiory pochodzi z Ruby on Rails.

Nazwany podzbiór reprezentuje nazwane kryteria zapytania, które mogą być połączone z innymi nazwanymi podzbiorami
i zastosowane do zapytania generowanego przez rekord aktywny.

Nazwane podzbiory deklarowane są głównie w metodzie CActiveRecord::scopes() jako pary nazwa-kryterium. Następujący kod definiuje dwa nazwane podzbiory, opublikowane oraz najnowsze w klasie modelu tbl_ost:

class Post extends CActiveRecord
{
    ......
    public function scopes()
    {
        return array(
            'published'=>array(
                'condition'=>'status=1',
            ),
            'recently'=>array(
                'order'=>'create_time DESC',
                'limit'=>5,
            ),
        );
    }
}

Każdy nazwany podzbiór jest definiowany jako tablica, która może zostać użyta do inicjalizacji instancji klasy CDbCriteria. Na przykład, nazwany zbiór najnowsze określa właściwość order jako createTime DESC oraz nadaje właściwości limit wartość 5, które przetłumaczone na kryteria zapytania, powinny zwrócić ostatnich 5 postów.

Nazwane podzbiory używane są najczęściej jako modyfikatory dla wywołań metody find. Kilka nazwanych podzbiorów może zostać ze sobą połączonych i w rezultacie tego zwrócić bardziej ograniczony zbiór wynikowy. Na przykład, aby znaleźć ostatnio opublikowane posty, możemy użyć następującego kodu:

$posts=Post::model()->obublikowane()->najnowsze()->findAll();

Ogólnie rzecz biorąc, nazwane podzbiory musza pojawić się po lewej stronie od wywołania metody find. Każde z nich dostarcza kryteria zapytania , które są łączone z pozostałymi kryteriami, włączając w to te, które zostały przekazane do metody find. Efekt końcowy jest podobny do tego,
jakby do zapytania dodano listę filtrów.

Uwaga: Nazwane podzbiory mogą być tylko używane wyłącznie z poziomu metod klasowych.
Oznacza to, że muszą one być wywołane w przy użyciu NazwaKlasy::model().

Parametryzowane nazwane podzbiory (ang. Parameterized Named Scopes)

Nazwane podzbiory mogą by sparametryzowane. Na przykład, chcemy dostosować liczbę postów określoną w nazwanym podzbiorze najnowsze Aby to zrobić, zamiast deklarować nazwany podzbiór w metodzie CActiveRecord::scopes, musimy zdefiniować nową metodę, której nazwa jest taka sama jak jak nazwa podzbioru:

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

Następnie, możemy używać następującego wyrażenia, aby uzyskać 3 ostatnie opublikowane posty:

$posts=Post::model()->opublikowane()->najnowsze(3)->findAll();

Jeśli w powyższym kodzie nie przekazalibyśmy 3, otrzymalibyśmy domyślnie 5 ostatnio opublikowanych postów.

Domyślne podzbiory

Klasa modelu może posiadać domyślne podzbiory, które będą stosowane dla wszystkich zapytań (włączająć w to zapytania relacyjne) dla modelu. Na przykład, strona wspierająca wielojęzyczność może chcież wyświetlać zawartość w aktualnie wybranym języku. Ponieważ, możemy mieć wiele zapytań związanych z zawartością strony, możemy zdecydować się na zdefiniowanie domyślnych podzbiorów, aby rozwiązać ten problem. Aby to zrobić, nadpisujemy metodę CActiveRecord::defaultScope w następujący sposób:

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

Od teraz, nastepujące wywołanie metody będzie automatycznie używało powyżej zdefiniowanych kreteriów zapytania:

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

Uwaga: Zauważ, że domyślne i nazwane podzbiory mają zastosowanie tylko dla zapytań SELECT. Są one ignorowane dla zapytań INSERT, UPDATE oraz DELETE. Ponadto, podczas deklarowania podzbiorów (domyślnych i nazwanych), klasa rekordu aktywnego nie może być używana do tworzenia zapytań do bazy w metodzie deklarującej podzbiór.

Found a typo or you think this page needs improvement?
Edit it on github !