Browse Source

Merge pull request #10539 from bizley/guide-pl

Guide PL [skip ci]
tags/2.0.7
Dmitry Naumenko 9 years ago
parent
commit
6831580790
  1. 2
      docs/guide-pl/README.md
  2. 649
      docs/guide-pl/input-validation.md
  3. 90
      docs/guide-pl/output-client-scripts.md
  4. 90
      docs/guide-pl/rest-error-handling.md
  5. 109
      docs/guide-pl/structure-entry-scripts.md
  6. 74
      docs/guide-pl/test-overview.md

2
docs/guide-pl/README.md

@ -103,7 +103,7 @@ Wyświetlanie danych
* [Sortowanie](output-sorting.md)
* [Dostawcy danych](output-data-providers.md)
* [Widżety danych](output-data-widgets.md)
* [Praca ze skryptami po stronie klienta](output-client-scripts.md)
* [Praca ze skryptami](output-client-scripts.md)
* [Skórki i motywy (Theming)](output-theming.md)

649
docs/guide-pl/input-validation.md

@ -0,0 +1,649 @@
Walidacja danych wejściowych
================
Jedna z głównych zasad mówi, że nigdy nie powinno ufać się danym otrzymanym od użytkowników oraz zawsze je walidować przez użyciem.
Mamy [model](structure-models.md) wypełniony danymi od użytkownika. Możemy go zwalidować przez wywołanie metody [[yii\base\Model::validate()|validate()]].
Metoda zwróci wartość `boolean` wskazującą, czy walidacja się powiodła, czy nie. Jeśli nie, możesz pobrać informacje o błędach za pomocą właściwości [[yii\base\Model::errors|errors]].
Dla przykładu,
```php
$model = new \app\models\ContactForm();
// uzupełniamy model danymi od użytkownika
$model->load(\Yii::$app->request->post());
// ten zapis jest tożsamy z poniższą metodą
// $model->attributes = \Yii::$app->request->post('ContactForm');
if ($model->validate()) {
// akcja w przypadku poprawnej walidacji
} else {
// akcja w przypadku niepoprawnej walidacji. Zmienna $errors jest tablicą zawierającą wiadomości błędów
$errors = $model->errors;
}
```
## Deklaracja zasad <span id="declaring-rules"></span>
Aby metoda [[yii\base\Model::validate()|validate()]] naprawdę zadziałała, powinieneś zadeklarować zasady walidacji dla atrybutów, które mają jej podlegać.
Powinno zostać to zrobione przez nadpisanie metody [[yii\base\Model::rules()|rules()]]. Poniższy przykład pokazuje jak zostały zadeklarowane zasady walidacji dla modelu `ContactForm`:
```php
public function rules()
{
return [
// atrybuty name, email, subject oraz body są wymagane
[['name', 'email', 'subject', 'body'], 'required'],
// atrybut email powinien być poprawnym adresem email
['email', 'email'],
];
}
```
Metoda [[yii\base\Model::rules()|rules()]] powinna zwracać tablicę zasad, gdzie każda zasada jest tablicą w następującym formacie:
```php
[
// wymagane, określa atrybut który powinien zostać zwalidowany przez tę zasadę.
// Dla pojedyńczego atrybutu możemy użyć bezpośrednio jego nazwy, bez osadzania go w tablicy
['attribute1', 'attribute2', ...],
// wymagane, określa typ tej zasady walidacji
// Może to być nazwa klasy, alias walidatora lub nazwa metody walidacji
'validator',
// opcjonalny, określa, w którym scenariuszu/scenariuszach ta zasada powinna zostać użyta
// w przypadku nie podania żadnego argumentu zasada zostanie zaaplikowana do wszystkich scenariuszy
// Możesz również skonfigurować opcję "except" jeśli chcesz użyć tej zasady dla wszystkich scenariuszy. oprócz tych wymienionych przez Ciebie
'on' => ['scenario1', 'scenario2', ...],
// opcjonalny, określa dodatkowe konfiguracje do obiektu walidatora
'property1' => 'value1', 'property2' => 'value2', ...
]
```
Dla każdej z zasad musisz określić co najmniej jeden atrybut, którego ma ona dotyczyć, oraz należy określić typ tej zasady.
Możesz określić typ zasady jako jedną z następujących form:
* alias walidatora podstawowego, np. `required`, `in`, `date` itd. Zajrzyj do sekcji [Podstawowe walidatory](tutorial-core-validators.md) aby uzyskać pełną listę walidatorów podstawowych.
* nazwa metody walidacji w klasie modelu, lub funkcja anonimowa. Po więcej szczegółów zajrzyj do sekcji [Inline Validators](#inline-validators).
* pełna nazwa klasy walidatora. Po więcej szczegółów zajrzyj do sekcji [Standalone Validators](#standalone-validators).
Zasada może zostać użyta do walidacji jednego lub wielu atrybutów, a atrybut może być walidowany przez jedną, lub wiele zasad.
Zasada może zostać użyta dla konkretnych [scenariuszy](structure-models.md#scenarios) przez określenie opcji `on`.
Jeśli nie określisz opcji `on` oznacza to, że zasada zostanie użyta w każdym scenariuszu.
Kiedy zostaje wywołana metoda [[yii\base\Model::validate()|validate()]] zostają wykonane następujące kroki w celu wykonania walidacji:
1. Określenie które atrybuty powinny zostać zwalidowane przez pobranie listy atrybutów z [[yii\base\Model::scenarios()|scenarios()]] używając aktualnego
[[yii\base\Model::scenario|scenario]]. Wybrane atrybuty nazywane są *atrybutami aktywnymi*.
2. Określenie które zasady walidacji powinny zostać użyte przez pobranie listy zasad z [[yii\base\Model::rules()|rules()]] używając aktualnego [[yii\base\Model::scenario|scenario]].
Wybrane zasady nazywane są *zasadami aktywnymi*.
3. Użycie każdej aktywnej zasady do walidacji każdego aktywnego atrybutu, który jest powiązany do konkretnej zasady. Zasady walidacji są wykonywane w kolejności w jakiej zostały zapisane.
Odnosząc się do powyższych kroków walidacji, atrybut zostanie zwalidowany wtedy i tylko wtedy, gdy jest on aktywnym atrybutem zadeklarowanym w
[[yii\base\Model::scenarios()|scenarios()]] oraz jest powiązany z jedną lub wieloma aktywnymi zasadami zadeklarowanymi w [[yii\base\Model::rules()|rules()]].
### Dostosowywanie wiadomości błedów <span id="customizing-error-messages"></span>
Większość walidatorów posiada domyślne wiadomości błędów, które zostaną dodane do poddanego walidacji modelu, kiedy któryś z atrybutów nie przejdzie walidacji.
Dla przykładu, walidator [[yii\validators\RequiredValidator|required]] doda wiadomość "Username cannot be blank." do modelu, jeśli atrybut `username` nie przejdzie walidacji tej zasady.
Możesz dostosować wiadomość błędu danej zasady przez określenie właściwości `message` przy deklaracji zasady.
Dla przykładu,
```php
public function rules()
{
return [
['username', 'required', 'message' => 'Proszę wybrać login.'],
];
}
```
Niektóre walidatory mogą wspierać dodatkowe wiadomości błedów, aby bardziej precyzyjnie określić problemy przy walidacji.
Dla przykładu, walidator [[yii\validators\NumberValidator|number]] dodaje [[yii\validators\NumberValidator::tooBig|tooBig]] oraz [[yii\validators\NumberValidator::tooSmall|tooSmall]]
do opisania sytuacji, kiedy liczba jest za duża lub za mała podczas walidacji. Możesz skonfigurować te wiadomości tak, jak pozostałe właściwości walidatorów w zasadzie walidacji.
### Zdarzenia walidacji <span id="validation-events"></span>
Podczas wywołania metody [[yii\base\Model::validate()|validate()]] zostaną wywołane dwie metody, które możesz nadpisać, aby dostosować proces walidacji:
* [[yii\base\Model::beforeValidate()|beforeValidate()]]: domyślna implementacja wywoła zdarzenie [[yii\base\Model::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]]. Możesz nadpisać tę
metodę lub odnieść się do zdarzenia, aby wykonać dodatkowe operacje przed walidacją. Metoda powinna zwracać wartość `boolean` wskazującą, czy walidacja powinna zostać wykonana, czy nie.
* [[yii\base\Model::afterValidate()|afterValidate()]]: domyślna implementacja wywoła zdarzenie [[yii\base\Model::EVENT_AFTER_VALIDATE|EVENT_AFTER_VALIDATE]]. Możesz nadpisać tę metodę
lub odnieść się do zdarzenia, aby wykonać dodatkowe operacje po zakończonej walidacji.
### Walidacja warunkowa <span id="conditional-validation"></span>
Aby zwalidować atrybuty tylko wtedy, gdy zostaną spełnione pewne założenia, np. walidacja jednego atrybutu zależy od wartości drugiego atrybutu, możesz użyć właściwości
[[yii\validators\Validator::when|when]] aby zdefiniować taki warunek. Dla przykładu,
```php
[
['state', 'required', 'when' => function($model) {
return $model->country == 'USA';
}],
]
```
Właściwość [[yii\validators\Validator::when|when]] pobiera możliwą do wywołania funkcję PHP z następującą definicją:
```php
/**
* @param Model $model model, który podlega walidacji
* @param string $attribute atrybut, który podlega walidacji
* @return boolean wartość zwrotna; czy reguła powinna zostać zastosowana
*/
function ($model, $attribute)
```
Jeśli potrzebujesz również wsparcia walidacji warunkowej po stronie użytkownika, powinieneś skonfigurować właściwość [[yii\validators\Validator::whenClient|whenClient]],
która przyjmuje wartość `string` reprezentującą funkcję JavaScript, zwracającą wartość `boolean`, która będzie określała, czy zasada powinna zostać zastosowana, czy nie.
Dla przykładu,
```php
[
['state', 'required', 'when' => function ($model) {
return $model->country == 'USA';
}, 'whenClient' => "function (attribute, value) {
return $('#country').val() == 'USA';
}"],
]
```
### Filtrowanie danych <span id="data-filtering"></span>
Dane od użytkownika często muszą zostać przefiltrowane. Dla przykładu, możesz chcieć wyciąć znaki spacji na początku i na końcu pola `username`.
Aby osiągnąć ten cel, możesz użyć zasad walidacji.
Poniższy przykład pokazuje, jak wyciąć znaki spacji z pola oraz zmienić puste pole na wartość `NULL` przy użyciu podstawowych walidatorów [trim](tutorial-core-validators.md#trim) oraz
[default](tutorial-core-validators.md#default):
```php
[
[['username', 'email'], 'trim'],
[['username', 'email'], 'default'],
]
```
Możesz użyć również bardziej ogólnego walidatora [filter](tutorial-core-validators.md#filter), aby przeprowadzić bardziej złożone filtrowanie.
Jak pewnie zauważyłeś, te zasady walidacji tak naprawdę nie walidują danych. Zamiast tego przetwarzają wartości, a następnie przypisują je do atrybutów, które zostały poddane walidacji.
### Obsługa pustych danych wejściowych <span id="handling-empty-inputs"></span>
Kiedy dane wejściowe są wysłane przez formularz HTML, często zachodzi potrzeba przypisania im domyślnych wartości jeśli są puste.
Możesz to osiągnąć przez użycie walidatora [default](tutorial-core-validators.md#default). Dla przykładu,
```php
[
// ustawia atrybuty "username" oraz "email" jako `NULL` jeśli są puste
[['username', 'email'], 'default'],
// ustawia atrybut "level" równy "1" jeśli jest pusty
['level', 'default', 'value' => 1],
]
```
Domyślnie pole uważane jest za puste, jeśli jego wartość to pusty string, pusta tablica lub `NULL`.
Możesz dostosować domyślną logikę wykrywania pustych pól przez skonfigurowanie parametru [[yii\validators\Validator::isEmpty|isEmpty]], przekazując mu funkcję PHP.
Dla przykładu,
```php
[
['agree', 'required', 'isEmpty' => function ($value) {
return empty($value);
}],
]
```
> Note: Większość walidatorów nie obsługuje pustych pól, jeśli ich właściwość [[yii\base\Validator::skipOnEmpty|skipOnEmpty] przyjmuje domyślnie wartość `true`.
Zostaną one po prostu pominięte podczas walidacji, jeśli ich powiązany atrybut otrzyma wartość uznawaną za pustą.
Wśród [podstawowych walidatorów](tutorial-core-validators.md), tylko walidatory `captcha`, `default`, `filter`, `required` oraz `trim` obsługują puste pola.
## Walidacja "Ad Hoc" <span id="ad-hoc-validation"></span>
Czasami potrzebna będzie walidacja *ad hoc* dla wartości które nie są powiązane z żadnym modelem.
Jeśli potrzebujesz wykonać tylko jeden typ walidacji (np. walidacja adresu email), możesz wywołać metodę [[yii\validators\Validator::validate()|validate()]] wybranego walidatora, tak
jak poniżej:
```php
$email = 'test@example.com';
$validator = new yii\validators\EmailValidator();
if ($validator->validate($email, $error)) {
echo 'Email is valid.';
} else {
echo $error;
}
```
> Note: Nie każdy walidator wspiera tego typu walidację. Dla przykładu, podstawowy walidator [unique](tutorial-core-validators.md#unique) został zaprojektowany do pracy wyłącznie z modelami.
Jeśli potrzebujesz przeprowadzić wielokrotne walidacje, możesz użyć [[yii\base\DynamicModel|DynamicModel]], który wspiera deklarację atrybutów oraz zasad walidacji "w locie".
Dla przykładu,
```php
public function actionSearch($name, $email)
{
$model = DynamicModel::validateData(compact('name', 'email'), [
[['name', 'email'], 'string', 'max' => 128],
['email', 'email'],
]);
if ($model->hasErrors()) {
// validation fails
} else {
// validation succeeds
}
}
```
Metoda [[yii\base\DynamicModel::validateData()|validateData()]] tworzy instancję `DynamicModel`, definiuje atrybuty używając przekazanych danych (`name` oraz `email` w tym przykładzie),
a następnie wywołuje metodę [[yii\base\Model::validate()|validate()]] z podanymi zasadami walidacji.
Alternatywnie, możesz użyć bardziej "klasycznego" zapisu to przeprowadzenia tego typu walidacji:
```php
public function actionSearch($name, $email)
{
$model = new DynamicModel(compact('name', 'email'));
$model->addRule(['name', 'email'], 'string', ['max' => 128])
->addRule('email', 'email')
->validate();
if ($model->hasErrors()) {
// validation fails
} else {
// validation succeeds
}
}
```
Po walidacji możesz sprawdzić, czy przebiegła ona poprawnie lub nie, przez wywołanie metody [[yii\base\DynamicModel::hasErrors()|hasErrors()]],
a następnie pobrać błędy walidacji z właściwości [[yii\base\DynamicModel::errors|errors]], tak jak w normalnym modelu.
Możesz również uzyskać dostęp do dynamicznych atrybutów tej instancji, np. `$model->name` and `$model->email`.
## Tworzenie walidatorów <span id="creating-validators"></span>
Oprócz używania [podstawowych walidatorów](tutorial-core-validators.md) dołączonych do wydania Yii, możesz dodatkowo utworzyć własne: wbudowane lub niezależne.
### Walidatory wbudowane <span id="inline-validators"></span>
Wbudowany walidator jest zdefiniowaną w modelu metodą lub funkcją anonimową. Jej definicja jest następująca:
```php
/**
* @param string $attribute atrybut podlegający walidacji
* @param mixed $params wartość parametru podanego w zasadzie walidacji
*/
function ($attribute, $params)
```
Jeśli atrybut nie przejdzie walidacji, metoda/funkcja powinna wywołać metodę [[yii\base\Model::addError()|addError()]] do zapisania wiadomości błędu w modelu,
aby mogła ona zostać później pobrana i zaprezentowana użytkownikowi.
Poniżej znajduje się kilka przykładów:
```php
use yii\base\Model;
class MyForm extends Model
{
public $country;
public $token;
public function rules()
{
return [
// Wbudowany walidator zdefiniowany jako metoda validateCountry() w modelu
['country', 'validateCountry'],
// Wbudowany walidator zdefiniowany jako funkcja anonimowa
['token', function ($attribute, $params) {
if (!ctype_alnum($this->$attribute)) {
$this->addError($attribute, 'Token musi zawierać litery lub cyfry.');
}
}],
];
}
public function validateCountry($attribute, $params)
{
if (!in_array($this->$attribute, ['USA', 'Web'])) {
$this->addError($attribute, 'Wybrany kraj musi być jednym z: "USA", "Web".');
}
}
}
```
> Note: Domyślnie wbudowane walidatory nie zostaną zastosowane, jeśli ich powiązane atrybuty otrzymają puste wartości lub wcześniej nie przeszły którejś z zasad walidacji.
> Jeśli chcesz się upewnić, że zasada zawsze zostanie zastosowana, możesz skonfigurować właściwość [[yii\validators\Validator::skipOnEmpty|skipOnEmpty]] i/lub
> [[yii\validators\Validator::skipOnError|skipOnError]] przypisując jej wartość `false` w deklaracji zasady walidacji. Dla przykładu:
>
> ```php
> [
> ['country', 'validateCountry', 'skipOnEmpty' => false, 'skipOnError' => false],
> ]
> ```
### Walidatory niezależne <span id="standalone-validators"></span>
Walidator niezależy jest klasą rozszerzającą [[yii\validators\Validator|Validator]] lub klasy po nim dziedziczące.
Możesz zaimplementować jego logikę walidacji przez nadpisanie metody [[yii\validators\Validator::validateAttribute()|validateAttribute()]].
Jeśli atrybut nie przejdzie walidacji, wywołaj metodę [[yii\base\Model::addError()|addError()]] do zapisania wiadomości błędu w modelu, tak jak w
[walidatorach wbudowanych](#inline-validators).
Dla przykładu, poprzedni wbudowany walidator mógłby zostać przeniesiony do nowej klasy `components/validators/CountryValidator`.
```php
namespace app\components;
use yii\validators\Validator;
class CountryValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (!in_array($model->$attribute, ['USA', 'Web'])) {
$this->addError($model, $attribute, 'Wybrany kraj musi być jednym z: "USA", "Web".');
}
}
}
```
Jeśli chcesz, aby walidator wspierał walidację wartości bez modelu, powinieneś nadpisać metodę [[yii\validators\Validator::validate()|validate()]].
Możesz nadpisać także [[yii\validators\Validator::validateValue()|validateValue()]] zamiast `validateAttribute()` oraz `validate()`,
ponieważ domyślnie te dwie metody są implementowane użyciem metody `validateValue()`.
Poniżej znajduje się przykład, jak mógłbyś użyć powyższej klasy walidatora w swoim modelu.
```php
namespace app\models;
use Yii;
use yii\base\Model;
use app\components\validators\CountryValidator;
class EntryForm extends Model
{
public $name;
public $email;
public $country;
public function rules()
{
return [
[['name', 'email'], 'required'],
['country', CountryValidator::className()],
['email', 'email'],
];
}
}
```
## Walidacja po stronie klienta <span id="client-side-validation"></span>
Walidacja po stronie klienta bazująca na kodzie JavaScript jest wskazana, kiedy użytkownicy dostarczają dane przez formularz HTML,
ponieważ pozwala na szybszą walidację błędów, a tym samym zapewnia lepszą ich obsługę dla użytkownika. Możesz użyć lub zaimplementować walidator, który wspiera walidację po stronie
klienta *dodatkowo do* walidacji po stronie serwera.
> Info: Walidacja po stronie klienta nie jest wymagana. Głównym jej celem jest poprawa jakości korzystania z formularzy przez użytkowników.
Podobnie do danych wejściowych pochodzących od użytkowników, nigdy nie powinieneś ufać walidacji po stronie klienta. Z tego powodu,
powinieneś zawsze przeprowadzać walidację po stronie serwera wywołując metodę [[yii\base\Model::validate()|validate()]], tak jak zostało to opisane w poprzednich sekcjach.
### Używanie walidacji po stronie klienta <span id="using-client-side-validation"></span>
Wiele [podstawowych walidatorów](tutorial-core-validators.md) domyślnie wspiera walidację po stronie klienta. Wszystko, co musisz zrobić, to użyć widżetu
[[yii\widgets\ActiveForm|ActiveForm]] do zbudowania formularza HTML. Dla przykładu, model `LoginForm` poniżej deklaruje dwie zasady: jedną, używającą podstawowego walidatora
[required](tutorial-core-validators.md#required), który wspiera walidację po stronie klienta i serwera, oraz drugą, w której użyto walidatora wbudowanego `validatePassword`, który
wspiera tylko walidację po stronie klienta.
```php
namespace app\models;
use yii\base\Model;
use app\models\User;
class LoginForm extends Model
{
public $username;
public $password;
public function rules()
{
return [
// atrybuty username oraz password są wymagane
[['username', 'password'], 'required'],
// atrybut password jest walidowany przez validatePassword()
['password', 'validatePassword'],
];
}
public function validatePassword()
{
$user = User::findByUsername($this->username);
if (!$user || !$user->validatePassword($this->password)) {
$this->addError('password', 'Nieprawidłowa nazwa użytkownika lub hasło.');
}
}
}
```
Formularz HTML zbudowany przez następujący kod zawiera dwa pola: `username` oraz `password`.
Jeśli wyślesz formularz bez wpisywania jakichkolwiek danych, otrzymasz komunikaty błędów o ich braku, bez konieczności przeprowadzania komunikacji z serwerem.
```php
<?php $form = yii\widgets\ActiveForm::begin(); ?>
<?= $form->field($model, 'username') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= Html::submitButton('Login') ?>
<?php yii\widgets\ActiveForm::end(); ?>
```
"Za kulisami", widżet [[yii\widgets\ActiveForm|ActiveForm]] odczyta wszystkie zasady walidacji zadeklarowane w modelu i wygeneruje odpowiedni kod JavaScript
dla walidatorów wspierających walidację po stronie klienta. Kiedy użytkownik zmieni wartość w polu lub spróbuje wysłać formularz, zostanie wywołana walidacja po stronie klienta.
Jeśli chcesz wyłączyć kompletnie walidację po stronie klienta, możesz ustawić właściwość [[yii\widgets\ActiveForm::enableClientValidation|enableClientValidation]] na `false`.
Możesz również wyłączyć ten rodzaj walidacji dla konkretnego pola, przez ustawienie jego właściwości
[[yii\widgets\ActiveField::enableClientValidation|enableClientValidation]] na `false`. Jeśli właściwość `enableClientValidation` zostanie skonfigurowana na poziomie pola formularza i w
samym formularzu jednocześnie, pierwszeństwo będzie miała opcja określona w formularzu.
### Implementacja walidacji po stronie klienta <span id="implementing-client-side-validation"></span>
Aby utworzyć walidator wspierający walidację po stronie klienta, powinieneś zaimplementować metodę [[yii\validators\Validator::clientValidateAttribute()|clientValidateAttribute()]],
która zwraca kod JavaScript, odpowiedzialny za przeprowadzenie walidacji. W kodzie JavaScript możesz użyć następujących predefiniowanych zmiennych:
- `attribute`: nazwa atrybutu podlegającego walidacji.
- `value`: wartość atrybutu podlegająca walidacji.
- `messages`: tablica używana do przechowywania wiadomości błędów dla danego atrybutu.
- `deferred`: tablica, do której można dodać zakolejkowane obiekty (wyjaśnione w późniejszej podsekcji).
W poniższym przykładzie, tworzymy walidator `StatusValidator`, który sprawdza, czy wartość danego atrybutu jest wartością znajdującą się w zbiorze statusów w bazie danych.
Walidator wspiera obydwa typy walidacji: po stronie klienta oraz serwerową.
```php
namespace app\components;
use yii\validators\Validator;
use app\models\Status;
class StatusValidator extends Validator
{
public function init()
{
parent::init();
$this->message = 'Niepoprawna wartość pola status.';
}
public function validateAttribute($model, $attribute)
{
$value = $model->$attribute;
if (!Status::find()->where(['id' => $value])->exists()) {
$model->addError($attribute, $this->message);
}
}
public function clientValidateAttribute($model, $attribute, $view)
{
$statuses = json_encode(Status::find()->select('id')->asArray()->column());
$message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return <<<JS
if ($.inArray(value, $statuses) === -1) {
messages.push($message);
}
JS;
}
}
```
> Tip: Powyższy kod został podany głównie do zademonstrowania jak wspierać walidację po stronie klienta.
> W praktyce można użyć podstawowego walidatora [in](tutorial-core-validators.md#in), aby osiągnąć ten sam cel.
> Możesz napisać taką zasadę walidacji następująco:
>
> ```php
> [
> ['status', 'in', 'range' => Status::find()->select('id')->asArray()->column()],
> ]
> ```
### Kolejkowa walidacja <span id="deferred-validation"></span>
Jeśli potrzebujesz przeprowadzić asynchroniczną walidację po stronie klienta, możesz utworzyć [obiekt kolejkujący](http://api.jquery.com/category/deferred-object/).
Dla przykładu, aby przeprowadzić niestandardową walidację AJAX, możesz użyć następującego kodu:
```php
public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
deferred.push($.get("/check", {value: value}).done(function(data) {
if ('' !== data) {
messages.push(data);
}
}));
JS;
}
```
W powyższym kodzie, zmienna `deferred` jest dostarczona przez Yii, która jest tablicą zakolejkowanych obiektów.
Metoda jQuery `$.get()` tworzy obiekt kolejkowy, który jest dodawany do tablicy `deferred`.
Możesz także utworzyć osobny obiekt kolejkowania i wywołać jego metodę `resolve()` po otrzymaniu asynchronicznej informacji zwrotnej.
Poniższy przykład pokazuje, jak zwalidować wymiary przesłanego obrazka po stronie klienta.
```php
public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
var def = $.Deferred();
var img = new Image();
img.onload = function() {
if (this.width > 150) {
messages.push('Image too wide!!');
}
def.resolve();
}
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
}
reader.readAsDataURL(file);
deferred.push(def);
JS;
}
```
> Note: Metoda `resolve()` musi być wywołana po zwalidowaniu atrybutu. W przeciwnym razie walidacja formularza nie zostanie ukończona.
Dla uproszczenia, tablica `deferred` jest wyposażona w skrótową metodę `add()`, która automatycznie tworzy obiekt kolejkowy i dodaje go do tej tablicy.
Używając tej metody, możesz uprościć powyższy przykład:
```php
public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
deferred.add(function(def) {
var img = new Image();
img.onload = function() {
if (this.width > 150) {
messages.push('Image too wide!!');
}
def.resolve();
}
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
}
reader.readAsDataURL(file);
});
JS;
}
```
### Walidacja przy użyciu AJAX <span id="ajax-validation"></span>
Niektóre walidacje mogą zostać wykonane tylko po stronie serwera, ponieważ tylko serwer posiada niezbędne informacje do ich przeprowadzenia.
Dla przykładu, aby sprawdzić, czy login został już zajęty, musimy sprawdzić tabelę użytkowników w bazie danych.
W tym właśnie przypadku możesz użyć walidacji AJAX. Wywoła ona żądanie AJAX w tle, aby spradzić to pole.
Aby uaktywnić walidację AJAX dla pojedyńczego pola formularza, ustaw właściwość [[yii\widgets\ActiveField::enableAjaxValidation|enableAjaxValidation]] na `true` oraz określ unikalne ID
formularza:
```php
use yii\widgets\ActiveForm;
$form = ActiveForm::begin([
'id' => 'registration-form',
]);
echo $form->field($model, 'username', ['enableAjaxValidation' => true]);
// ...
ActiveForm::end();
```
Aby uaktywnić walidację AJAX dla całego formularza, ustaw właściwość [[yii\widgets\ActiveForm::enableAjaxValidation|enableAjaxValidation]] na `true` na poziomie formularza:
```php
$form = ActiveForm::begin([
'id' => 'contact-form',
'enableAjaxValidation' => true,
]);
```
> Note: Jeśli właściwość [[yii\widgets\ActiveForm::enableAjaxValidation|enableAjaxValidation]] zostanie skonfigurowana na poziomie pola formularza i jednocześnie w samym formularzu,
pierwszeństwo będzie miała opcja określona w formularzu.
Musisz również przygotować serwer, aby mógł obsłużyć AJAXowe zapytanie o walidację. Możesz to osiągnąć przez następujący skrawek kodu w akcji kontrolera:
```php
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
```
Powyższy kod sprawdzi, czy zapytanie zostało wysłane przy użyciu AJAXa. Jeśli tak, w odpowiedzi zwróci wynik walidacji w formacie JSON.
> Info: Możesz również użyć [walidacji kolejkowej](#deferred-validation) do wykonania walidacji AJAX, jednakże walidacja AJAXowa opisana w tej sekcji jest bardziej systematyczna i
wymaga mniej wysiłku przy kodowaniu.

90
docs/guide-pl/output-client-scripts.md

@ -0,0 +1,90 @@
Praca ze skryptami
===========================
> Note: Ta sekcja nie została jeszcze ukończona.
### Rejestrowanie skryptów
Dzięki obiektowi [[yii\web\View|View]] możesz rejestrować skrypty w aplikacji. Przeznaczone są do tego dwie dedykowane metody:
[[yii\web\View::registerJs()|registerJs()]] dla skryptów wbudowanych oraz
[[yii\web\View::registerJsFile()|registerJsFile()]] dla skryptów zewnętrznych.
Skrypty wbudowane są przydatne przy konfiguracji oraz dynamicznym generowaniu kodu.
Możesz dodać je w następujący sposób:
```php
$this->registerJs("var options = " . json_encode($options) . ";", View::POS_END, 'my-options');
```
Pierwszy argument przekazywany do metody `registerJs` to kod JavaScript, który chcemy umieścić na stronie. Jako drugi argument wskazujemy miejsce,
w którym skrypt ma zostać umieszczony na stronie. Możliwe wartości to:
- [[yii\web\View::POS_HEAD|View::POS_HEAD]] dla sekcji `head`.
- [[yii\web\View::POS_BEGIN|View::POS_BEGIN]] zaraz po otwarciu tagu `<body>`.
- [[yii\web\View::POS_END|View::POS_END]] zaraz przed zamknięciem tagu `</body>`.
- [[yii\web\View::POS_READY|View::POS_READY]] do wywołania kodu z użyciem zdarzenia `ready` na dokumencie. Ta opcja zarejestruje automatycznie [[yii\web\JqueryAsset|jQuery]]
- [[yii\web\View::POS_LOAD|View::POS_LOAD]] do wywołania kodu z użyciem zdarzenia `load` na dokumencie. Ta opcja zarejestruje automatycznie [[yii\web\JqueryAsset|jQuery]]
Ostatnim argumentem jest unikalne ID skryptu, które jest używane do zidentyfikowania bloku kodu i zastąpienia go, jeśli taki został już zarejestrowany.
Jeśli ten argument nie zostanie podany, kod JavaScript zostanie użyty jako ID.
Skrypt zewnętrzny może zostać dodany następująco:
```php
$this->registerJsFile('http://example.com/js/main.js', ['depends' => [\yii\web\JqueryAsset::className()]]);
```
Argumenty dla metod [[yii\web\View::registerCssFile()|registerCssFile()]] są podobne do [[yii\web\View::registerJsFile()|registerJsFile()]].
W powyższym przykładzie, zarejestrowaliśmy plik `main.js` z zależnością od `JqueryAsset`. Oznacza to, że plik `main.js` zostanie dodany PO pliku `jquery.js`.
Bez określenia tej zależności, względny porządek pomiędzy `main.js` a `jquery.js` nie zostałby zachowany.
Tak jak i w przypadku [[yii\web\View::registerCssFile()|registerCssFile()]], mocno rekomendujemy, abyś użył [assetów](structure-assets.md) do zarejestrowania zewnętrznych plików JS
zamiast używania [[yii\web\View::registerJsFile()|registerJsFile()]].
### Rejestracja assetów
Jak zostało wspomniane wcześniej, korzystniejsze jest stosowanie assetów, zamiast kodu CSS i JS bezpośrednio (po informacje na ten temat sięgnij do sekcji
[menedżera assetów](structure-assets.md)).
Korzystanie z już zdefiniowanych pakietów jest bardzo proste:
```php
\frontend\assets\AppAsset::register($this);
```
### Rejestrowanie kodu CSS
Możesz zarejestrować kod CSS przy użyciu metody [[yii\web\View::registerCss()|registerCss()]] lub [[yii\web\View::registerCssFile()|registerCssFile()]].
Pierwsza z nich rejestruje blok kodu CSS, natomiast druga zewnętrzny plik `.css`. Dla przykładu:
```php
$this->registerCss("body { background: #f00; }");
```
Powyższy kod doda kod CSS do sekcji `head` strony:
```html
<style>
body { background: #f00; }
</style>
```
Jeśli chcesz określić dodatkowe właściwości dla tagu `style`, przekaż tablicę `nazwa => wartość` jako drugi argument.
Jeśli chcesz się upewnić, że jest tylko jeden tag `style`, użyj trzeciego argumentu, tak jak zostało to opisane dla meta tagów.
```php
$this->registerCssFile("http://example.com/css/themes/black-and-white.css", [
'depends' => [BootstrapAsset::className()],
'media' => 'print',
], 'css-print-theme');
```
Kod powyżej doda link w sekcji `head` strony do pliku CSS.
* Pierwszy argument określa, który plik ma zostać zarejestrowany,
* Drugi argument określa atrybuty tagu `<link>`. Opcja `depends` jest obsługiwana w specjalny sposób, od niej zależy położenie pliku CSS.
W tym przypadku, plik link do pliku CSS zostanie umieszony ZA plikami CSS w [[yii\bootstrap\BootstrapAsset|BootstrapAsset]],
* Ostatni argument określa ID identyfikujące ten plik CSS. W przypadku jego braku, zostanie użyty do tego celu adres URL pliku CSS.
Jest mocno wskazane używanie [assetów](structure-assets.md) do rejestrowania zewnętrznych plików CSS. Użycie ich pozwala Ci na łączenie i kompresowanie
wielu plików CSS, które jest wręcz niezbędne na stronach internetowych o dużym natężeniu ruchu.

90
docs/guide-pl/rest-error-handling.md

@ -0,0 +1,90 @@
Obsługa błędów
==============
Podczas obsługi żądania RESTfulowego API, w przypadku wystąpienia błędu w zapytaniu użytkownika lub gdy stanie się coś nieprzewidywanego
z serwerem, możesz po prostu rzucić wyjątkiem, aby powiadomić użytkownika, że coś poszło nieprawidłowo.
Jeśli możesz zidentyfikować przyczynę błędu (np. żądany zasób nie istnieje), powinieneś rozważyć
rzucenie wyjątkiem razem z odpowiednim kodem statusu HTTP (np. [[yii\web\NotFoundHttpException|NotFoundHttpException]] odpowiada statusowi o kodzie 404).
Yii wyśle odpowiedź razem z odpowiadającym jej kodem i treścią statusu HTTP. Yii dołączy również do samej odpowiedzi zserializowaną reprezentację
wyjątku. Przykładowo:
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
Poniższa lista zawiera kody statusów HTTP, które są używane przez Yii REST framework:
* `200`: OK. Wszystko działa w porządku.
* `201`: Zasób został poprawnie stworzony w odpowiedzi na żądanie `POST`. Nagłówek `Location` zawiera URL kierujący do nowoutworzonego zasobu.
* `204`: Żądanie zostało poprawnie przetworzone, ale odpowiedź nie zawiera treści (jak w przypadku żądania `DELETE`).
* `304`: Zasób nie został zmodyfikowany. Można użyć wersji przetrzymywanej w pamięci podręcznej.
* `400`: Nieprawidłowe żądanie. Może być spowodowane przez wiele czynników po stronie użytkownika, takich jak przekazanie nieprawidłowych danych JSON,
nieprawidłowych parametrów akcji, itp.
* `401`: Nieudana autentykacja.
* `403`: Autoryzowany użytkownik nie ma uprawnień do danego punktu końcowego API.
* `404`: Żądany zasób nie istnieje.
* `405`: Niedozwolona metoda. Sprawdź nagłówek `Allow`, aby poznać dozwolone metody HTTP.
* `415`: Niewspierany typ mediów. Żądany typ zawartości lub numer wersji jest nieprawidłowy.
* `422`: Nieudana walidacja danych (dla przykładu w odpowiedzi na żądanie `POST`). Sprawdź treść odpowiedzi, aby poznać szczegóły błędu.
* `429`: Zbyt wiele żądań. Żądanie zostało odrzucone z powodu osiagnięcia limitu użycia.
* `500`: Wewnętrzny błąd serwera. To może być spowodowane wewnętrznymi błędami programu.
## Modyfikowanie błędnej odpowiedzi <span id="customizing-error-response"></span>
Czasem wymagane może być dostosowanie domyślnego formatu błędnej odpowiedzi. Dla przykładu, zamiast używać różnych statusów HTTP dla oznaczenia różnych błędów,
można serwować zawsze status 200 i dodawać prawidłowy kod statusu HTTP jako część struktury JSON w odpowiedzi, jak pokazano to poniżej:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
Aby osiągnąć powyższy efekt, należy skonfigurować odpowiedź na event `beforeSend` dla komponentu `response` w aplikacji:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && Yii::$app->request->get('suppress_response_code')) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
Powyższy kod zreformatuje odpowiedź (zarówno typu sukces jak i błąd), kiedy `suppress_response_code` zostanie przekazane jako parametr `GET`.

109
docs/guide-pl/structure-entry-scripts.md

@ -0,0 +1,109 @@
Skrypty wejściowe
=================
Skrypty wejściowe są pierwszym krokiem procesu bootstrapowania aplikacji. Aplikacja (zarówno web
jak i konsolowa) posiada pojedynczy skrypt wejściowy. Użytkownicy końcowi wysyłają żądania do skryptów
wejściowych, które inicjują instancje aplikacji i przekazują do nich te żądania.
Skrypty wejściowe dla aplikacji Web muszą znajdować się w folderach dostępnych dla Web, aby użytkownicy końcowi mogli je wywołać.
Zwykle nazywane są `index.php`, ale mogą mieć inne nazwy pod warunkiem, że serwery Web potrafią je zlokalizować.
Skrypty wejściowe dla aplikacji konsolowych trzymane są zwykle w [ścieżce głównej](structure-applications.md)
aplikacji i nazywane `yii` (z sufiksem `.php`). Powinny być wykonywalne, aby użytkownicy
mogli uruchomić aplikacje konsolowe za pomocą komendy `./yii <ścieżka> [argumenty] [opcje]`.
Skrypty wejściowe wykonują głównie następującą pracę:
* Definiują globalne stałe,
* Rejestrują [autoloader Composera](https://getcomposer.org/doc/01-basic-usage.md#autoloading),
* Dołączają plik klasy [[Yii]],
* Ładują konfigurację aplikacji,
* Tworzą i konfigurują instancję [aplikacji](structure-applications.md),
* Wywołują [[yii\base\Application::run()|run()]], aby przetworzyć wysłane żądanie.
## Aplikacje Web <span id="web-applications"></span>
Poniżej znajdziesz kod skryptu wejściowego dla [Podstawowego projektu szablonu Web](start-installation.md).
```php
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
// register Composer autoloader
require(__DIR__ . '/../vendor/autoload.php');
// include Yii class file
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
// load application configuration
$config = require(__DIR__ . '/../config/web.php');
// create, configure and run application
(new yii\web\Application($config))->run();
```
## Aplikacje konsoli <span id="console-applications"></span>
Podobnie, poniżej kod skryptu wejściowego dla aplikacji konsolowej:
```php
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
// register Composer autoloader
require(__DIR__ . '/vendor/autoload.php');
// include Yii class file
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
// load application configuration
$config = require(__DIR__ . '/config/console.php');
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);
```
## Definiowanie stałych <span id="defining-constants"></span>
Skrypty wejściowe są najlepszym miejscem do definiowania globalnych stałych. Yii wspiera następujące trzy stałe:
* `YII_DEBUG`: określa czy aplikacja działa w trybie debugowania. Podczas tego trybu aplikacja
przetrzymuje więcej informacji w logach i zdradza szczegóły stosu błędów, kiedy rzucony jest wyjątek. Z tego powodu
tryb debugowania powinien być używany głównie podczas fazy deweloperskiej. Domyślną wartością `YII_DEBUG` jest false.
* `YII_ENV`: określa środowisko, w którym aplikacja działa. Opisane jest to bardziej szczegółowo
w sekcji [Konfiguracje](concept-configurations.md#environment-constants).
Domyślną wartością `YII_ENV` jest `'prod'`, co oznacza, że aplikacja jest uruchomiona w środowisku produkcyjnym.
* `YII_ENABLE_ERROR_HANDLER`: określa czy uruchomić obsługę błędów przygotowaną przez Yii. Domyślną wartością tej stałej jest true.
Podczas definiowania stałej często korzystamy z poniższego kodu:
```php
defined('YII_DEBUG') or define('YII_DEBUG', true);
```
co odpowiada:
```php
if (!defined('YII_DEBUG')) {
define('YII_DEBUG', true);
}
```
Jak widać pierwszy sposób jest bardziej zwięzły i łatwiejszy do zrozumienia.
Definiowanie stałych powinno odbyć się na samym początku skryptu wejściowego, aby odniosło skutek podczas dołączania pozostałych plików PHP.

74
docs/guide-pl/test-overview.md

@ -0,0 +1,74 @@
Testowanie
==========
Testowanie jest istotnym elementem produkcji każdego oprogramowania. Niezależnie, czy jesteśmy tego świadomi, czy też nie, testy przeprowadzamy nieustannie.
Dla przykładu, kiedy napiszemy klasę w PHP, możemy debugować ją krok po kroku lub po prostu użyć wyrażeń jak echo lub die, aby sprawdzić, czy implementacja
działa zgodnie z naszym początkowym planem. W przypadku aplikacji web wprowadzamy testowe dane w formularzach, aby upewnić się, że strona odpowiada tak, jak powinna.
Proces testowania może zostać zautomatyzowany, dzięki czemu za każdym razem, kiedy musimy coś sprawdzić, wystarczy wywołać kod, który zrobi to za nas.
Kod, który weryfikuje zgodność wyniku z planowaną odpowiedzią, jest nazywany testem, a proces jego tworzenia i późniejszego wykonania jest nazywany testowaniem zautomatyzowanym,
co jest głównym tematem tych rozdziałów.
Tworzenie kodu z testami
------------------------
Tworzenie kodu opartego na testach (Test-Driven Development, TDD) i opartego na zachowaniach (Behavior-Driven Development, BDD) jest podejściem deweloperskim
opierającym się na opisywaniu zachowania fragmentu kodu lub też całej jego funkcjonalności jako zestawu scenariuszy lub testów przed napisaniem właściwego kodu
i dopiero potem stworzeniu implementacji, która pozwoli na poprawne przejście testów, spełniających zadane kryteria.
Proces tworzenia funkcjonalności wygląda następująco:
- Stwórz nowy test, opisujący funkcjonalność do zaimplementowania.
- Uruchom nowy test i upewnij się, że zakończy się błędem. To właściwe zachowanie, ponieważ nie ma jeszcze implementacji funkcjonalności.
- Napisz prosty kod, który przejdzie poprawnie nowy test.
- Uruchom wszystkie testy i upewnij się, że wszystkie zakończą się poprawnie.
- Ulepsz kod, sprawdzając czy testy wciąż są zdane.
Po zakończeniu proces jest powtarzany dla kolejnej funkcjonalności lub ulepszenia. Jeśli istniejąca funkcjonalność ma być zmodyfikowana,
testy powinny być również zmienione.
> **Wskazówka**: Jeśli czujesz, że tracisz czas, przeprowadzając dużo krótkich i prostych iteracji, spróbuj objąć testowym scenariuszem więcej działań,
> aby sprawdzić więcej kodu, przed ponownym uruchomieniem testów. Jeśli debugujesz zbyt dużo, spróbuj zrobić dokładnie na odwrót.
Powodem tworzenia testów przed jakąkolwiek implementacją, jest możliwość skupienia się na tym, co chcemy osiągnąć, zanim przystąpimy do "w jaki sposób to zrobić".
Zwykle prowadzi to do stworzenia lepszej warstwy abstrakcji i łatwiejszej obsługi testów w przypadku poprawek funkcjonalności.
Podsumowując, zalety takiego projektowania są następujące:
- Pozwala na skupienie się na pojedynczej rzeczy na raz, dzięki czemu pozwala na lepsze planowanie i implementacje.
- Obejmuje testami więcej funkcjonalności w większym stopniu, co oznacza, że jeśli testy zakończyły się poprawnie jest spore prawdopodobieństwo, że wszystko działa poprawnie.
Na dłuższą metę przynosi to zwykle efekt w postaci mnóstwa oszczędzonego czasu i problemów.
> **Wskazówka**: Jeśli chcesz dowiedzieć się więcej na temat reguł ustalania wymagań dla oprogramowania i modelowania istoty tego rozdziału,
> warto zapoznać się z domenowym podejściem do tworzenia aplikacji [(Domain Driven Development, DDD)](https://pl.wikipedia.org/wiki/Domain-Driven_Design).
Kiedy i jak testować
--------------------
Podejście typu "testy najpierw" opisane powyżej, ma sens w przypadku długofalowych i relatywnie skomplikowanych projektów i może być przesadne w przypadku prostszych.
Przesłanki, kiedy testy są odpowiednie są następujące:
- Projekt jest już duży i skomplikowany.
- Wymagania projektowe zaczynają być skomplikowane. Projekt wciąż się powiększa.
- Projekt jest planowany jako długoterminowy.
- Koszty potencjalnych błędów są zbyt duże.
Nie ma nic złego w tworzeniu testów obejmujących zachowania istniejących implementacji.
- Projekt jest oparty starszym kodzie i stopniowo przepisywany.
- Projekt, nad którym masz pracować, nie ma w ogóle testów.
W niektórych przypadkach jakakolwiek forma automatycznego testu może być nadmiarowa:
- Projekt jest prosty i nie jest rozbudowywany.
- Projekt jest jednorazowym zadaniem, które nie będzie rozwijane.
Pomimo tego, jeśli masz na to czas, automatyzacja testowania jest również dobrym pomysłem.
Biblioteka
-------------
- Test Driven Development: By Example - Kent Beck. (ISBN: 0321146530)
Loading…
Cancel
Save