PL guide updated (#13909) [skip ci]


@ -147,7 +147,7 @@ Narzędzia wspomagające tworzenie aplikacji
|
|||||||
|
|
||||||
* [Pasek debugowania i debuger](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md)
|
* [Pasek debugowania i debuger](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md)
|
||||||
* [Generowanie kodu przy użyciu Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md)
|
* [Generowanie kodu przy użyciu Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md)
|
||||||
* **TBD** [Generowanie dokumentacji API](https://github.com/yiisoft/yii2-apidoc)
|
* [Generowanie dokumentacji API](https://github.com/yiisoft/yii2-apidoc)
|
||||||
|
|
||||||
|
|
||||||
Testowanie
|
Testowanie
|
||||||
@ -179,16 +179,16 @@ Tematy specjalne
|
|||||||
Widżety
|
Widżety
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* GridView: **TBD** link to demo page
|
* [GridView](http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html)
|
||||||
* ListView: **TBD** link to demo page
|
* [ListView](http://www.yiiframework.com/doc-2.0/yii-widgets-listview.html)
|
||||||
* DetailView: **TBD** link to demo page
|
* [DetailView](http://www.yiiframework.com/doc-2.0/yii-widgets-detailview.html)
|
||||||
* ActiveForm: **TBD** link to demo page
|
* [ActiveForm](http://www.yiiframework.com/doc-2.0/guide-input-forms.html#activerecord-based-forms-activeform)
|
||||||
* Pjax: **TBD** link to demo page
|
* [Pjax](http://www.yiiframework.com/doc-2.0/yii-widgets-pjax.html)
|
||||||
* Menu: **TBD** link to demo page
|
* [Menu](http://www.yiiframework.com/doc-2.0/yii-widgets-menu.html)
|
||||||
* LinkPager: **TBD** link to demo page
|
* [LinkPager](http://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html)
|
||||||
* LinkSorter: **TBD** link to demo page
|
* [LinkSorter](http://www.yiiframework.com/doc-2.0/yii-widgets-linksorter.html)
|
||||||
* [Widżety Bootstrapowe](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide/README.md)
|
* [Widżety Bootstrapowe](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide/README.md)
|
||||||
* [Widżety Jquery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/README.md)
|
* [Widżety jQuery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/README.md)
|
||||||
|
|
||||||
|
|
||||||
Klasy pomocnicze
|
Klasy pomocnicze
|
||||||
|
@ -2,8 +2,7 @@ Pamięć podręczna
|
|||||||
================
|
================
|
||||||
|
|
||||||
Mechanizmy wykorzystujące pamięć podręczną pozwalają na poprawienie wydajności aplikacji sieciowej w tani i efektywny sposób.
|
Mechanizmy wykorzystujące pamięć podręczną pozwalają na poprawienie wydajności aplikacji sieciowej w tani i efektywny sposób.
|
||||||
Zapisanie mniej lub bardziej statycznych danych w pamięci podręcznej i serwowanie ich stamtąd, zamiast generować je od podstaw przy każdym
|
Zapisanie statycznych danych w pamięci podręcznej, zamiast generowania ich od podstaw przy każdym wywołaniu, pozwala na znaczne zaoszczędzenie czasu odpowiedzi aplikacji.
|
||||||
wywołaniu, pozwala na znaczne zaoszczędzenie czasu odpowiedzi aplikacji.
|
|
||||||
|
|
||||||
Zapis pamięci podręcznej może odbywać się na wielu poziomach i w wielu miejscach aplikacji. Po stronie serwera, na niskim poziomie,
|
Zapis pamięci podręcznej może odbywać się na wielu poziomach i w wielu miejscach aplikacji. Po stronie serwera, na niskim poziomie,
|
||||||
można wykorzystać pamięć podręczną do zapisania podstawowych danych, takich jak zbiór informacji o najnowszych artykułach pobieranych z bazy danych.
|
można wykorzystać pamięć podręczną do zapisania podstawowych danych, takich jak zbiór informacji o najnowszych artykułach pobieranych z bazy danych.
|
||||||
|
@ -5,7 +5,7 @@ Pamięć podręczna stron odnosi się do zapisu zawartości całej strony po str
|
|||||||
zawartość zostanie wyświetlona od razu z pamięci podręcznej zamiast generować ją ponownie od podstaw.
|
zawartość zostanie wyświetlona od razu z pamięci podręcznej zamiast generować ją ponownie od podstaw.
|
||||||
|
|
||||||
Pamięć podręczna stron jest obsługiwana przez [filtr akcji](structure-filters.md) [[yii\filters\PageCache|PageCache]].
|
Pamięć podręczna stron jest obsługiwana przez [filtr akcji](structure-filters.md) [[yii\filters\PageCache|PageCache]].
|
||||||
Poniżej znajdziesz przykładowy sposób użycia w klasie kontrolera:
|
Poniżej znajdziesz przykładowy sposób użycia go w klasie kontrolera:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
public function behaviors()
|
public function behaviors()
|
||||||
@ -27,13 +27,13 @@ public function behaviors()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
W powyższym przykładzie kod zakłada użycie pamięci tylko dla akcji `index` - zawartość strony powinna zostać zapisana na maksymalnie
|
W powyższym przykładzie zakładamy użycie pamięci podręcznej tylko dla akcji `index` - zawartość strony powinna zostać zapisana na maksymalnie
|
||||||
60 sekund i powinna różnić się w zależności od wybranego w aplikacji języka. Dodatkowo, jeśli całkowita liczba postów w bazie danych ulegnie zmianie,
|
60 sekund i powinna różnić się w zależności od wybranego w aplikacji języka. Dodatkowo, jeśli całkowita liczba postów w bazie danych ulegnie zmianie,
|
||||||
zawartość pamięci powinna natychmiast stracić ważność i zostać pobrana ponownie.
|
zawartość pamięci powinna natychmiast stracić ważność i zostać pobrana ponownie.
|
||||||
|
|
||||||
Jak widać, pamięć podręczna stron jest bardzo podobna do [pamięci podręcznej fragmentów](caching-fragment.md). W obu przypadkach można
|
Jak widać, pamięć podręczna stron jest bardzo podobna do [pamięci podręcznej fragmentów](caching-fragment.md). W obu przypadkach można
|
||||||
użyć opcji takich jak `duration` (czas ważności), `dependencies` (zależności), `variations` (warianty) oraz `enabled` (flaga aktywowania).
|
użyć opcji takich jak `duration` (czas ważności), `dependencies` (zależności), `variations` (warianty) oraz `enabled` (flaga aktywowania).
|
||||||
Główną różnicą tych dwóch przypadków jest to, że pamięć podręczna stron jest implemetowana jako [filtr akcji](structure-filters.md), a
|
Główną różnicą w tych dwóch przypadkach jest to, że pamięć podręczna stron jest implemetowana jako [filtr akcji](structure-filters.md), a
|
||||||
pamięć podręczna fragmentów jako [widżet](structure-widgets.md).
|
pamięć podręczna fragmentów jako [widżet](structure-widgets.md).
|
||||||
|
|
||||||
Oczywiście nic nie stoi na przeszkodzie, aby używać [pamięci podręcznej fragmentów](caching-fragment.md) jak
|
Oczywiście nic nie stoi na przeszkodzie, aby używać [pamięci podręcznej fragmentów](caching-fragment.md) jak
|
||||||
|
@ -9,7 +9,7 @@ Trzy główne funkcjonalności, które zapewniają komponenty innym klasom to:
|
|||||||
* [Behaviory (zachowania)](concept-behaviors.md)
|
* [Behaviory (zachowania)](concept-behaviors.md)
|
||||||
|
|
||||||
Wszystkie razem i każda z tych funkcjonalności osobno zapewnia klasom Yii o wiele większą elastyczność i łatwość użycia. Dla przykładu,
|
Wszystkie razem i każda z tych funkcjonalności osobno zapewnia klasom Yii o wiele większą elastyczność i łatwość użycia. Dla przykładu,
|
||||||
dołączony [[yii\jui\DatePicker|widżet wybierania daty]], komponent interfejsu użytkownika, może być użyty w [widoku](structure-view.md),
|
dołączony [[yii\jui\DatePicker|widżet wybierania daty]], komponent interfejsu użytkownika, może być użyty w [widoku](structure-views.md),
|
||||||
aby wygenerować interaktywny kalendarz:
|
aby wygenerować interaktywny kalendarz:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
@ -47,9 +47,19 @@ W tej sekcji przewodnika opiszemy sposób użycia Active Record dla baz relacyjn
|
|||||||
|
|
||||||
## Deklarowanie klas Active Record <span id="declaring-ar-classes"></span>
|
## Deklarowanie klas Active Record <span id="declaring-ar-classes"></span>
|
||||||
|
|
||||||
Na początek zadeklaruj klasę typu Active Record rozszerzając [[yii\db\ActiveRecord|ActiveRecord]]. Ponieważ każda klasa Active Record
|
Na początek zadeklaruj klasę typu Active Record rozszerzając [[yii\db\ActiveRecord|ActiveRecord]].
|
||||||
jest powiązana z tabelą bazy danych, należy nadpisać metodę [[yii\db\ActiveRecord::tableName()|tableName()]], aby wskazać
|
|
||||||
odpowiednią tabelę.
|
### Deklarowanie nazwy tabeli
|
||||||
|
|
||||||
|
Domyślnie każda klasa Active Record jest powiązana ze swoją tabelą w bazie danych.
|
||||||
|
Metoda [[yii\db\ActiveRecord::tableName()|tableName()]] zwraca nazwę tabeli konwertując nazwę klasy za pomocą [[yii\helpers\Inflector::camel2id()]].
|
||||||
|
Możesz przeciążyć tę metodę, jeśli tabela nie jest nazwana zgodnie z tą konwencją.
|
||||||
|
|
||||||
|
Identycznie zastosowany może być domyślny prefiks tabeli [[yii\db\Connection::$tablePrefix|tablePrefix]]. Przykładowo, jeśli
|
||||||
|
[[yii\db\Connection::$tablePrefix|tablePrefix]] to `tbl_`, tabelą klasy `Customer` staje się `tbl_customer`, a dla `OrderItem` jest to `tbl_order_item`.
|
||||||
|
|
||||||
|
Jeśli nazwa tabeli zostanie podana jako `{{%NazwaTabeli}}`, znak procent `%` zostanie zamieniony automatycznie na prefiks tabeli.
|
||||||
|
Dla przykładu, `{{%post}}` staje się `{{tbl_post}}`. Nawiasy wokół nazwy tabeli są używane dla odpowiedniego [podawania nazw w kwerendach SQL](db-dao.md#quoting-table-and-column-names).
|
||||||
|
|
||||||
W poniższym przykładzie deklarujemy klasę Active Record nazwaną `Customer` dla tabeli `customer` w bazie danych.
|
W poniższym przykładzie deklarujemy klasę Active Record nazwaną `Customer` dla tabeli `customer` w bazie danych.
|
||||||
|
|
||||||
@ -68,11 +78,12 @@ class Customer extends ActiveRecord
|
|||||||
*/
|
*/
|
||||||
public static function tableName()
|
public static function tableName()
|
||||||
{
|
{
|
||||||
return 'customer';
|
return '{{customer}}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Aktywne rekordy nazywane są "modelami"
|
||||||
Instancje Active Record są traktowane jak [modele](structure-models.md). Z tego powodu zwykle dodajemy klasy Active Record
|
Instancje Active Record są traktowane jak [modele](structure-models.md). Z tego powodu zwykle dodajemy klasy Active Record
|
||||||
do przestrzeni nazw `app\models` (lub innej, przeznaczonej dla klas modeli).
|
do przestrzeni nazw `app\models` (lub innej, przeznaczonej dla klas modeli).
|
||||||
|
|
||||||
@ -444,6 +455,26 @@ $customer->loadDefaultValues();
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Rzutowanie typów atrybutów <span id="attributes-typecasting"></span>
|
||||||
|
|
||||||
|
Po wypełnieniu rezultatem kwerendy, [[yii\db\ActiveRecord]] przeprowadza automatyczne rzutowanie typów na wartościach swoich atrybutów,
|
||||||
|
używając do tego celu informacji zawartych w [schemacie tabeli bazy danych](db-dao.md#database-schema). Pozwala to na prawidłowe przedstawienie
|
||||||
|
danych pobranych z kolumny tabeli zadeklarowanej jako liczba całkowita, w postaci wartości typu PHP integer w instancji klasy ActiveRecord (typu boolean jako boolean itp.).
|
||||||
|
Mechanizm rzutowania ma jednak kilka ograniczeń:
|
||||||
|
|
||||||
|
* Wartości typu zmiennoprzecinkowego nie są konwertowane na float, a zamiast tego są przedstawiane jako łańcuch znaków, aby zachować dokładność ich liczbowej prezentacji.
|
||||||
|
* Konwersja typu integer zależy od zakresu liczb całkowitych używanego systemu operacyjnego.
|
||||||
|
Wartości kolumn zadeklarowanych jako 'unsigned integer' lub 'big integer' będą przekonwertowane do PHP integer tylko na systemach 64-bitowych,
|
||||||
|
a na 32-bitowych będą przedstawione jako łańcuchy znaków.
|
||||||
|
|
||||||
|
Zwróć uwagę na to, że rzutowanie typów jest wykonywane tylko podczas wypełniania instancji ActiveRecord rezultatem kwerendy. Automatyczna konwersja nie jest przeprowadzana
|
||||||
|
dla wartości załadowanych poprzez żądanie HTTP lub ustawionych bezpośrednio dla właściwości klasy.
|
||||||
|
Schemat tabeli będzie również użyty do przygotowania instrukcji SQL przy zapisywaniu danych ActiveRecord, aby upewnić się, że wartości są przypisane w kwerendzie z prawidłowymi typami.
|
||||||
|
Atrybuty instancji ActiveRecord nie będą jednak przekonwertowane w procesie zapisywania.
|
||||||
|
|
||||||
|
> Tip: możesz użyć [[yii\behaviors\AttributeTypecastBehavior]], aby skonfigurować proces rzutowania typów dla wartości atrybutów w momencie ich walidacji lub zapisu.
|
||||||
|
|
||||||
|
|
||||||
### Aktualizowanie wielu wierszy jednocześnie <span id="updating-multiple-rows"></span>
|
### Aktualizowanie wielu wierszy jednocześnie <span id="updating-multiple-rows"></span>
|
||||||
|
|
||||||
Metody przedstawione powyżej działają na pojedynczych instancjach Active Record, dodając lub aktualizując indywidualne wiersze tabeli.
|
Metody przedstawione powyżej działają na pojedynczych instancjach Active Record, dodając lub aktualizując indywidualne wiersze tabeli.
|
||||||
@ -575,9 +606,16 @@ try {
|
|||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
$transaction->rollBack();
|
$transaction->rollBack();
|
||||||
throw $e;
|
throw $e;
|
||||||
|
} catch(\Throwable $e) {
|
||||||
|
$transaction->rollBack();
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Note: w powyższym kodzie znajdują się dwa bloki catch dla kompatybilności
|
||||||
|
> z PHP 5.x i PHP 7.x. `\Exception` implementuje [interfejs `\Throwable`](http://php.net/manual/en/class.throwable.php)
|
||||||
|
> od PHP 7.0, zatem można pominąć część z `\Exception`, jeśli Twoja aplikacja używa tylko PHP 7.0 lub wyższego.
|
||||||
|
|
||||||
Drugi sposób polega na utworzeniu listy operacji bazodanowych, które wymagają transakcji za pomocą metody [[yii\db\ActiveRecord::transactions()|transactions()]].
|
Drugi sposób polega na utworzeniu listy operacji bazodanowych, które wymagają transakcji za pomocą metody [[yii\db\ActiveRecord::transactions()|transactions()]].
|
||||||
Dla przykładu:
|
Dla przykładu:
|
||||||
|
|
||||||
@ -961,7 +999,7 @@ W powyższym przykładzie modyfikujemy relacyjną kwerendę dodając warunek ze
|
|||||||
>
|
>
|
||||||
> ```php
|
> ```php
|
||||||
> $orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
|
> $orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
|
||||||
> // $orders[0]->customer ma zawsze wartość null. Aby rozwiązać ten problem, należy użyć:
|
> // $orders[0]->customer ma zawsze wartość `null`. Aby rozwiązać ten problem, należy użyć:
|
||||||
> $orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
|
> $orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
@ -1065,6 +1103,16 @@ Od wersji 2.0.7, Yii udostępnia do tego celu skróconą metodę. Możliwe jest
|
|||||||
$query->joinWith(['orders o'])->orderBy('o.id');
|
$query->joinWith(['orders o'])->orderBy('o.id');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Powyższy kod działa dla prostych relacji. Jeśli jednak potrzebujesz aliasu dla tabeli dołączonej w zagnieżdżonej relacji,
|
||||||
|
np. `$query->joinWith(['orders.product'])`, musisz rozwinąć wywołanie `joinWith` jak w poniższym przykładzie:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$query->joinWith(['orders o' => function($q) {
|
||||||
|
$q->joinWith('product p');
|
||||||
|
}])
|
||||||
|
->where('o.amount > 100');
|
||||||
|
```
|
||||||
|
|
||||||
### Odwrócone relacje <span id="inverse-relations"></span>
|
### Odwrócone relacje <span id="inverse-relations"></span>
|
||||||
|
|
||||||
Deklaracje relacji są zazwyczaj obustronne dla dwóch klas Active Record. Przykładowo `Customer` jest powiązany z `Order` poprzez relację `orders`,
|
Deklaracje relacji są zazwyczaj obustronne dla dwóch klas Active Record. Przykładowo `Customer` jest powiązany z `Order` poprzez relację `orders`,
|
||||||
@ -1253,10 +1301,10 @@ Domyślnie wszystkie kwerendy Active Record używają klasy [[yii\db\ActiveQuery
|
|||||||
należy nadpisać metodę [[yii\db\ActiveRecord::find()|find()]], aby zwracała instancję żądanej klasy kwerend. Przykład:
|
należy nadpisać metodę [[yii\db\ActiveRecord::find()|find()]], aby zwracała instancję żądanej klasy kwerend. Przykład:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
// plik Comment.php
|
||||||
namespace app\models;
|
namespace app\models;
|
||||||
|
|
||||||
use yii\db\ActiveRecord;
|
use yii\db\ActiveRecord;
|
||||||
use yii\db\ActiveQuery;
|
|
||||||
|
|
||||||
class Comment extends ActiveRecord
|
class Comment extends ActiveRecord
|
||||||
{
|
{
|
||||||
@ -1265,33 +1313,39 @@ class Comment extends ActiveRecord
|
|||||||
return new CommentQuery(get_called_class());
|
return new CommentQuery(get_called_class());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommentQuery extends ActiveQuery
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Od tego momentu, za każdym razem, gdy wykonywana będzie kwerenda (np. `find()`, `findOne()`) lub pobierana relacja (np. `hasOne()`) klasy `Comment`,
|
Od tego momentu, za każdym razem, gdy wykonywana będzie kwerenda (np. `find()`, `findOne()`) lub pobierana relacja (np. `hasOne()`) klasy `Comment`,
|
||||||
praca będzie odbywać się na instancji `CommentQuery` zamiast `ActiveQuery`.
|
praca będzie odbywać się na instancji `CommentQuery` zamiast `ActiveQuery`.
|
||||||
|
|
||||||
> Tip: Dla dużych projektów rekomendowane jest, aby używać własnych, odpowiednio dopasowanych do potrzeb, klas kwerend, dzięki czemu klasy Active Record
|
Teraz należy zdefiniować klasę `CommentQuery`, którą można dopasować do własnych kreatywnych potrzeb, dzięki czemu budowanie zapytań bazodanowych będzie o wiele bardziej ułatwione. Dla przykładu,
|
||||||
> pozostają przejrzyste.
|
|
||||||
|
|
||||||
Możesz dopasować klasę kwerend do własnych potrzeb na wiele kreatywnych sposobów. Przykładowo, możesz zdefiniować nowe metody konstruujące zapytanie:
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
// plik CommentQuery.php
|
||||||
|
namespace app\models;
|
||||||
|
|
||||||
|
use yii\db\ActiveQuery;
|
||||||
|
|
||||||
class CommentQuery extends ActiveQuery
|
class CommentQuery extends ActiveQuery
|
||||||
{
|
{
|
||||||
|
// dodatkowe warunki relacyjnej kwerendy dołączone jako domyślne (ten krok można pominąć)
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->andOnCondition(['deleted' => false]);
|
||||||
|
parent::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... dodaj zmodyfikowane metody kwerend w tym miejscu ...
|
||||||
|
|
||||||
public function active($state = true)
|
public function active($state = true)
|
||||||
{
|
{
|
||||||
return $this->andWhere(['active' => $state]);
|
return $this->andOnCondition(['active' => $state]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> Note: Zwykle, zamiast wywoływać metodę [[yii\db\ActiveQuery::where()|where()]], powinno się używać metody
|
> Note: Zwykle, zamiast wywoływać metodę [[yii\db\ActiveQuery::onCondition()|onCondition()]], powinno się używać metody
|
||||||
> [[yii\db\ActiveQuery::andWhere()|andWhere()]] lub [[yii\db\ActiveQuery::orWhere()|orWhere()]], aby dołączać kolejne warunki zapytania w
|
> [[yii\db\ActiveQuery::andOnCondition()|andOnCondition()]] lub [[yii\db\ActiveQuery::orOnCondition()|orOnCondition()]], aby dołączać kolejne warunki zapytania w
|
||||||
> konstruktorze kwerend, dzięki czemu istniejące warunki nie zostaną nadpisane.
|
> konstruktorze kwerend, dzięki czemu istniejące warunki nie zostaną nadpisane.
|
||||||
|
|
||||||
Powyższy przykład pozwala na użycie następującego kodu:
|
Powyższy przykład pozwala na użycie następującego kodu:
|
||||||
@ -1301,6 +1355,9 @@ $comments = Comment::find()->active()->all();
|
|||||||
$inactiveComments = Comment::find()->active(false)->all();
|
$inactiveComments = Comment::find()->active(false)->all();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Tip: Dla dużych projektów rekomendowane jest, aby używać własnych, odpowiednio dopasowanych do potrzeb, klas kwerend, dzięki czemu klasy Active Record
|
||||||
|
> pozostają przejrzyste.
|
||||||
|
|
||||||
Możesz także użyć nowych metod budowania kwerend przy definiowaniu relacji z `Comment` lub wykonywaniu relacyjnych kwerend:
|
Możesz także użyć nowych metod budowania kwerend przy definiowaniu relacji z `Comment` lub wykonywaniu relacyjnych kwerend:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
@ -1312,11 +1369,18 @@ class Customer extends \yii\db\ActiveRecord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$customers = Customer::find()->with('activeComments')->all();
|
$customers = Customer::find()->joinWith('activeComments')->all();
|
||||||
|
|
||||||
// lub alternatywnie
|
// lub alternatywnie
|
||||||
|
class Customer extends \yii\db\ActiveRecord
|
||||||
$customers = Customer::find()->with([
|
{
|
||||||
|
public function getComments()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Comment::className(), ['customer_id' => 'id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$customers = Customer::find()->joinWith([
|
||||||
'comments' => function($q) {
|
'comments' => function($q) {
|
||||||
$q->active();
|
$q->active();
|
||||||
}
|
}
|
||||||
@ -1394,8 +1458,9 @@ $customers = Customer::find()
|
|||||||
->all();
|
->all();
|
||||||
```
|
```
|
||||||
|
|
||||||
Wadą tej metody jest to, że jeśli informacja nie może zostać pobrana za pomocą kwerendy SQL, musi ona być obliczona oddzielnie,
|
Wadą tej metody jest to, że jeśli informacja nie może zostać pobrana za pomocą kwerendy SQL, musi ona być obliczona oddzielnie.
|
||||||
co oznacza rónież, że świeżo zapisane rekordy nie będą zawierały informacji z dodatkowych pól:
|
Zatem po pobraniu konkretnego wiersza tabeli za pomocą regularnej kwerendy bez dodatkowej instrukcji select, niemożliwym będzie
|
||||||
|
zwrócenie wartości dla dodatkowych pól. Tak samo stanie się w przypadku świeżo zapisanych rekordów.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$room = new Room();
|
$room = new Room();
|
||||||
@ -1403,7 +1468,7 @@ $room->length = 100;
|
|||||||
$room->width = 50;
|
$room->width = 50;
|
||||||
$room->height = 2;
|
$room->height = 2;
|
||||||
|
|
||||||
$room->volume; // ta wartość będzie wynosić null ponieważ nie została jeszcze zadeklarowana
|
$room->volume; // ta wartość będzie wynosić `null` ponieważ nie została jeszcze zadeklarowana
|
||||||
```
|
```
|
||||||
|
|
||||||
Używając magicznych metod [[yii\db\BaseActiveRecord::__get()|__get()]] i [[yii\db\BaseActiveRecord::__set()|__set()]], możemy emulować
|
Używając magicznych metod [[yii\db\BaseActiveRecord::__get()|__get()]] i [[yii\db\BaseActiveRecord::__set()|__set()]], możemy emulować
|
||||||
@ -1438,9 +1503,9 @@ class Room extends \yii\db\ActiveRecord
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Kiedy kwerenda nie zapewnii wartości kubatury, model będzie w stanie automatycznie ją obliczyć, używając swoich atrybutów.
|
Kiedy kwerenda nie zapewni wartości kubatury, model będzie w stanie automatycznie ją obliczyć, używając swoich atrybutów.
|
||||||
|
|
||||||
Podobnego sposobu można użyć na dodatkowych polach zależnych od danych tabel relacji:
|
Możesz obliczyć sumaryczne pola rónież korzystając ze zdefiniowanych relacji:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
class Customer extends \yii\db\ActiveRecord
|
class Customer extends \yii\db\ActiveRecord
|
||||||
@ -1459,7 +1524,7 @@ class Customer extends \yii\db\ActiveRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_ordersCount === null) {
|
if ($this->_ordersCount === null) {
|
||||||
$this->setOrdersCount(count($this->orders));
|
$this->setOrdersCount($this->getOrders()->count()); // oblicz sumę na żądanie z relacji
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_ordersCount;
|
return $this->_ordersCount;
|
||||||
@ -1473,3 +1538,54 @@ class Customer extends \yii\db\ActiveRecord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Dla powyższego kodu, kiedy 'ordersCount' występuje w instrukcji 'select' - `Customer::ordersCount` zostanie wypełnione
|
||||||
|
rezultatem kwerendy, w pozostałych przypadkach zostanie obliczone na żądanie używając relacji `Customer::orders`.
|
||||||
|
|
||||||
|
Takie podejście może być równie dobrze użyte do stworzenia skrótów dla niektórych danych relacji, zwłąszcza tych służących do obliczania sumarycznego.
|
||||||
|
Przykładowo:
|
||||||
|
|
||||||
|
```php
|
||||||
|
class Customer extends \yii\db\ActiveRecord
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Deklaracja wirtualnej właściwości tylko do odczytu dla danych sumarycznych.
|
||||||
|
*/
|
||||||
|
public function getOrdersCount()
|
||||||
|
{
|
||||||
|
if ($this->isNewRecord) {
|
||||||
|
return null; // to pozwala na uniknięcie uruchamiania wyszukującej kwerendy dla pustych kluczy głównych
|
||||||
|
}
|
||||||
|
|
||||||
|
return empty($this->ordersAggregation) ? 0 : $this->ordersAggregation[0]['counted'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deklaracja zwykłej relacji 'orders'.
|
||||||
|
*/
|
||||||
|
public function getOrders()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deklaracja nowej relacji bazującej na 'orders', ale zapewniającej pobranie danych sumarycznych.
|
||||||
|
*/
|
||||||
|
public function getOrdersAggregation()
|
||||||
|
{
|
||||||
|
return $this->getOrders()
|
||||||
|
->select(['customer_id', 'counted' => 'count(*)'])
|
||||||
|
->groupBy('customer_id')
|
||||||
|
->asArray(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Customer::find()->with('ordersAggregation')->all() as $customer) {
|
||||||
|
echo $customer->ordersCount; // wyświetla dane sumaryczne z relacji bez dodatkowej kwerendy dzięki gorliwemu pobieraniu
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer = Customer::findOne($pk);
|
||||||
|
$customer->ordersCount; // wyświetla dane sumaryczne z relacji pobranej leniwie
|
||||||
|
```
|
||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 50 KiB |