diff --git a/docs/guide-pl/README.md b/docs/guide-pl/README.md index b89ce96b21..8f715312ac 100644 --- a/docs/guide-pl/README.md +++ b/docs/guide-pl/README.md @@ -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) * [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 @@ -179,16 +179,16 @@ Tematy specjalne Widżety ------- -* GridView: **TBD** link to demo page -* ListView: **TBD** link to demo page -* DetailView: **TBD** link to demo page -* ActiveForm: **TBD** link to demo page -* Pjax: **TBD** link to demo page -* Menu: **TBD** link to demo page -* LinkPager: **TBD** link to demo page -* LinkSorter: **TBD** link to demo page +* [GridView](http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html) +* [ListView](http://www.yiiframework.com/doc-2.0/yii-widgets-listview.html) +* [DetailView](http://www.yiiframework.com/doc-2.0/yii-widgets-detailview.html) +* [ActiveForm](http://www.yiiframework.com/doc-2.0/guide-input-forms.html#activerecord-based-forms-activeform) +* [Pjax](http://www.yiiframework.com/doc-2.0/yii-widgets-pjax.html) +* [Menu](http://www.yiiframework.com/doc-2.0/yii-widgets-menu.html) +* [LinkPager](http://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html) +* [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 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 diff --git a/docs/guide-pl/caching-overview.md b/docs/guide-pl/caching-overview.md index d2a05f6baf..70fd70220a 100644 --- a/docs/guide-pl/caching-overview.md +++ b/docs/guide-pl/caching-overview.md @@ -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. -Zapisanie mniej lub bardziej statycznych danych w pamięci podręcznej i serwowanie ich stamtąd, zamiast generować je od podstaw przy każdym -wywołaniu, pozwala na znaczne zaoszczędzenie czasu odpowiedzi aplikacji. +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. 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. diff --git a/docs/guide-pl/caching-page.md b/docs/guide-pl/caching-page.md index 7de78b40a3..940274bb2b 100644 --- a/docs/guide-pl/caching-page.md +++ b/docs/guide-pl/caching-page.md @@ -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. 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 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, 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 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). Oczywiście nic nie stoi na przeszkodzie, aby używać [pamięci podręcznej fragmentów](caching-fragment.md) jak diff --git a/docs/guide-pl/concept-components.md b/docs/guide-pl/concept-components.md index 2feaa22bed..5db0591669 100644 --- a/docs/guide-pl/concept-components.md +++ b/docs/guide-pl/concept-components.md @@ -9,7 +9,7 @@ Trzy główne funkcjonalności, które zapewniają komponenty innym klasom to: * [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, -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: ```php diff --git a/docs/guide-pl/db-active-record.md b/docs/guide-pl/db-active-record.md index 72866623cf..ef70f84057 100644 --- a/docs/guide-pl/db-active-record.md +++ b/docs/guide-pl/db-active-record.md @@ -47,9 +47,19 @@ W tej sekcji przewodnika opiszemy sposób użycia Active Record dla baz relacyjn ## Deklarowanie klas Active Record -Na początek zadeklaruj klasę typu Active Record rozszerzając [[yii\db\ActiveRecord|ActiveRecord]]. Ponieważ każda klasa Active Record -jest powiązana z tabelą bazy danych, należy nadpisać metodę [[yii\db\ActiveRecord::tableName()|tableName()]], aby wskazać -odpowiednią tabelę. +Na początek zadeklaruj klasę typu Active Record rozszerzając [[yii\db\ActiveRecord|ActiveRecord]]. + +### 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. @@ -68,11 +78,12 @@ class Customer extends ActiveRecord */ 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 do przestrzeni nazw `app\models` (lub innej, przeznaczonej dla klas modeli). @@ -444,6 +455,26 @@ $customer->loadDefaultValues(); ``` +### Rzutowanie typów atrybutów + +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 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) { $transaction->rollBack(); 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()]]. Dla przykładu: @@ -961,7 +999,7 @@ W powyższym przykładzie modyfikujemy relacyjną kwerendę dodając warunek ze > > ```php > $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(); > ``` @@ -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'); ``` +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 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: ```php +// plik Comment.php namespace app\models; use yii\db\ActiveRecord; -use yii\db\ActiveQuery; class Comment extends ActiveRecord { @@ -1265,33 +1313,39 @@ class Comment extends ActiveRecord 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`, 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 -> 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: +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, ```php +// plik CommentQuery.php +namespace app\models; + +use yii\db\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) { - 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 -> [[yii\db\ActiveQuery::andWhere()|andWhere()]] lub [[yii\db\ActiveQuery::orWhere()|orWhere()]], aby dołączać kolejne warunki zapytania w +> Note: Zwykle, zamiast wywoływać metodę [[yii\db\ActiveQuery::onCondition()|onCondition()]], powinno się używać metody +> [[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. 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(); ``` +> 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: ```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 - -$customers = Customer::find()->with([ +class Customer extends \yii\db\ActiveRecord +{ + public function getComments() + { + return $this->hasMany(Comment::className(), ['customer_id' => 'id']); + } +} + +$customers = Customer::find()->joinWith([ 'comments' => function($q) { $q->active(); } @@ -1394,8 +1458,9 @@ $customers = Customer::find() ->all(); ``` -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: +Wadą tej metody jest to, że jeśli informacja nie może zostać pobrana za pomocą kwerendy SQL, musi ona być obliczona oddzielnie. +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 $room = new Room(); @@ -1403,7 +1468,7 @@ $room->length = 100; $room->width = 50; $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ć @@ -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 class Customer extends \yii\db\ActiveRecord @@ -1459,7 +1524,7 @@ class Customer extends \yii\db\ActiveRecord } if ($this->_ordersCount === null) { - $this->setOrdersCount(count($this->orders)); + $this->setOrdersCount($this->getOrders()->count()); // oblicz sumę na żądanie z relacji } 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 +``` diff --git a/docs/guide-pl/images/start-gii-crud-preview.png b/docs/guide-pl/images/start-gii-crud-preview.png index 85c2355f2e..a8912e2829 100644 Binary files a/docs/guide-pl/images/start-gii-crud-preview.png and b/docs/guide-pl/images/start-gii-crud-preview.png differ diff --git a/docs/guide-pl/images/start-gii-crud.png b/docs/guide-pl/images/start-gii-crud.png index 77c1ada18a..948e6cd131 100644 Binary files a/docs/guide-pl/images/start-gii-crud.png and b/docs/guide-pl/images/start-gii-crud.png differ diff --git a/docs/guide-pl/images/start-gii-model-preview.png b/docs/guide-pl/images/start-gii-model-preview.png index 080be64b1f..3b6eb9f488 100644 Binary files a/docs/guide-pl/images/start-gii-model-preview.png and b/docs/guide-pl/images/start-gii-model-preview.png differ diff --git a/docs/guide-pl/images/start-gii-model.png b/docs/guide-pl/images/start-gii-model.png index 59c16a477e..9c506dee00 100644 Binary files a/docs/guide-pl/images/start-gii-model.png and b/docs/guide-pl/images/start-gii-model.png differ