start-forms.md 13.7 KB
Newer Older
RichWeber committed
1 2 3
Робота з формами
================

4 5
В даному розділі ми обговоримо отримання даних від користувачів. На сторінці буде розміщена форма з полями, 
де можна буде вказати ім’я та email. Отримані дані будуть зображені на сторінці для їх підтвердження.
RichWeber committed
6

7
Для того, щоб досягти дану ціль, крім створення [дії](structure-controllers.md) і двох [представлень](structure-views.md)
RichWeber committed
8 9 10 11
ви створите [модель](structure-models.md).

В даному керівництві ви дізнаєтесь:

12 13 14
* Як створити [модель](structure-models.md) для даних, вказаних користувачем
* Як оголосити правила перевірки введених даних
* Як створити HTML форму в [представленні](structure-views.md)
RichWeber committed
15 16 17


Створення моделі <a name="creating-model"></a>
18
----------------
RichWeber committed
19

20 21 22
Створіть клас моделі `EntryForm` та збережіть у файлі `models/EntryForm.php` як показано нижче. Він буде використовуватись
для зберігання даних, введених користувачем. Детальніше про присвоєння імен файлам класів читайте в розділі
[Автозавантаження класів](concept-autoloading.md).
RichWeber committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

```php
<?php

namespace app\models;

use yii\base\Model;

class EntryForm extends Model
{
    public $name;
    public $email;

    public function rules()
    {
        return [
            [['name', 'email'], 'required'],
            ['email', 'email'],
        ];
    }
}
```

Даний клас розширює клас [[yii\base\Model]], який є складовою частиною фреймворка і зазвичай використовується для роботи з даними форм.

48 49 50 51
> Інформація: Клас [[yii\base\Model]] використовується як батьківський клас для класів моделей, які *не* асоційовані
  з таблицями бази даних. Клас [[yii\db\ActiveRecord]] зазвичай є батьківським для класів моделей, що відповідають 
  таблицям бази даних.

RichWeber committed
52
Клас містить 2 публічні властивості `name` і `email`, які використовуються для зберігання даних, вказаних користувачем.
53 54
Він також містить метод `rules()`, який повертає набір правил перевірки даних. Правила перевірки, 
оголошені в коді вище означають наступне:
RichWeber committed
55

56 57
* Поля `name` і `email` обов’язкові для заповнення
* Поле `email` повино містити правильну адресу email
RichWeber committed
58 59 60 61 62

Якщо об’єкт `EntryForm` заповнений даними користувача, то для їх перевірки ви можете викликати метод
[[yii\base\Model::validate()|validate()]]. У випадку невдалої перевірки властивість [[yii\base\Model::hasErrors|hasErrors]]
дорівнюватиме `true`. За допомогою [[yii\base\Model::getErrors|errors]] можна дізнатись, які саме виникли помилки.

63 64 65 66 67 68 69 70 71 72 73 74 75
```php
<?php
$model = new EntryForm();
$model->name = 'Qiang';
$model->email = 'bad';
if ($model->validate()) {
    // Good!
} else {
    // Failure!
    // Use $model->getErrors()
}
```

RichWeber committed
76

77 78
Створення дії <a name="creating-action"></a>
-------------
RichWeber committed
79

80 81
Далі створіть дію `entry` в контролері `site`, точно так, як ви робили це раніше.
Процес створення та використання дій описано у розділі [Говоримо «Привіт»](start-hello.md).
RichWeber committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

```php
<?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\EntryForm;

class SiteController extends Controller
{
    // ...існуючий код...

    public function actionEntry()
    {
        $model = new EntryForm;

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
101
            // дані в $model успішно перевірені
RichWeber committed
102 103 104 105 106 107 108 109 110 111 112 113 114

            // робимо щось корисне з $model ...
 
            return $this->render('entry-confirm', ['model' => $model]);
        } else {
            // або сторінка відображається вперше, або ж є помилка в даних
            return $this->render('entry', ['model' => $model]);
        }
    }
}
```

Подія створює об’єкт `EntryForm`. Потім вона намагається заповнити модель даними із масива `$_POST`, доступ
115 116 117 118 119 120
до якого забеспечує Yii за допомогою [[yii\web\Request::post()]]. Якщо модель успішно заповнена, тобто користувач відправив 
дані з HTML форми, то для перевірки даних буде викликаний метод [[yii\base\Model::validate()|validate()]].

> Інформація: `Yii::$app` являє собою глобально доступний екземпляр-одинак [додатка](structure-applications.md) 
  (singleton). Одночасно це є [Service Locator](concept-service-locator.md), який надає доступ до компонентів, типу 
  `request`, `response`, `db` і так далі. В коді выще для доступу до даних з `$_POST` був використаний компонент `request`.
RichWeber committed
121 122 123 124

Якщо все гаразд, подія зобразить представлення `entry-confirm`, яке покаже користувачу вказані ним дані.
В іншому випадку буде зображено представлення `entry`, яке містить HTML форму і помилки перевірки даних, якщо вони є.

125 126 127
> Примітка: У цьому дуже простому прикладі ми просто відобразили сторінку підтвердження відправки даних.
  На практиці, ви повинні розглянути використання [[yii\web\Controller::refresh()|refresh()]] або [[yii\web\Controller::redirect()|redirect()]]
  для уникнення [проблеми повторного відправлення даних форми](http://en.wikipedia.org/wiki/Post/Redirect/Get).
RichWeber committed
128 129 130


Створення представлення <a name="creating-views"></a>
131
-----------------------
RichWeber committed
132

133
На завершення, створюємо два представлення з іменами `entry-confirm` і `entry`, котрі зображаються дією `entry` з минулого підрозділу.
RichWeber committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

Представлення `entry-confirm` просто зображає ім’я та email. Воно мусить бути збережене у файлі `views/site/entry-confirm.php`.

```php
<?php
use yii\helpers\Html;
?>
<p>Ви вказали наступну інформацію:</p>

<ul>
    <li><label>Name</label>: <?= Html::encode($model->name) ?></li>
    <li><label>Email</label>: <?= Html::encode($model->email) ?></li>
</ul>
```

Представлення `entry` відображає HTML форму. Воно мусить бути збережене у файлі `views/site/entry.php`.

```php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'name') ?>

    <?= $form->field($model, 'email') ?>

    <div class="form-group">
        <?= Html::submitButton('Надіслати', ['class' => 'btn btn-primary']) ?>
    </div>

<?php ActiveForm::end(); ?>
```

Для побудови HTML форми представлення використовує потужний [віджет](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]].
170 171
Методи `begin()` і `end()` виводять відкриваючий і закриваючий теги форми. Між цими викликами створюються поля для заповнення 
за допомогою метода [[yii\widgets\ActiveForm::field()|field()]]. Першим іде поле для "name", другим — для "email".
RichWeber committed
172 173 174
Далі для генерації кнопки відправлення даних викликається метод [[yii\helpers\Html::submitButton()]].


175 176
Спробуємо <a name="trying-it-out"></a>
---------
RichWeber committed
177

178
Щоб побачити, як це працює, відкрийте в браузері наступний URL:
RichWeber committed
179 180 181 182 183 184 185 186 187

```
http://hostname/index.php?r=site/entry
```

Ви побачите сторінку з формою і двома полями для заповнення. Перед кожним полем є надпис, який вказує, яку саме
інформацію слід вказувати. Якщо ви натиснете на кнопку відправлення даних без самих даних або якщо вкажете email в невірному
форматі, то ви побачите повідомлення з помилкою біля кожного проблемного поля.

188
![Форма з помилками](images/start-form-validation.png)
RichWeber committed
189 190 191

Після введення вірних даних і їх відправки, ви побачите сторінку з даними, які щойно вказали.

192
![Підтвердження введених даних](images/start-entry-confirmation.png)
RichWeber committed
193 194


195
### Як працює вся ця "магія" <a name="magic-explained"></a>
RichWeber committed
196

197 198 199
Ви, більш за все, ставите питанням про те, як все ж ця HTML форма працює насправді і яким чином. 
Весь процес може здатися трохи магічним: те як зображаються підписи до полів, помилки перевірки даних при некоректному 
заповненні і те що все це відбувається без перезавантаження сторінки.
RichWeber committed
200

201 202 203 204 205
Так, початкова перевірка даних дійсно проходить на стороні клієнта за допомогою JavaScript, і повторно перевіряється
на стороні сервера (PHP). [[yii\widgets\ActiveForm]] достатньо продуманий, щоб взяти правила перевірки, які ви 
оголосили в `EntryForm`, перетворити їх в JavaScript код і використовувати його для проведення перевірки. 
На випадок, якщо в браузері буде вимкнено JavaScript валідація проходить і на стороні сервера, як показано в методі 
`actionEntry()`. Це дає впевненість в тому, що дані коректні за будь-яких обставин.
RichWeber committed
206

207 208
> Попередження: перевірка даних на стороні клієнта це зручність, яке забезпечує кращий користувальницький досвід.
  Перевірка на стороні сервера завжди обов’язкова, незважаючи на клієнтську.
RichWeber committed
209 210 211 212 213 214 215 216 217 218

Підписи для полів генеруються методом `field()`, на основі імен властивостей моделі. Наприклад, підпис `Name` генерується
для властивості `name`. Ви можете модифікувати підписи наступним чином:

```php
<?= $form->field($model, 'name')->label('Ваше ім’я') ?>
<?= $form->field($model, 'email')->label('Ваш Email') ?>
```

> Інформація: У Yii є велика кількість віджетів, які дозволяють швидко будувати складні і динамічні представлення.
219 220
  Як ви дізнаєтесь пізніше, розробляти нові віджети доволі просто. Багато із представленнь можна винести у віджети, 
  щоб використовувати їх повторно в інших частинах і тим самим спростити розробку в майбутньому.
RichWeber committed
221

222 223
Підсумок <a name="summary"></a>
--------
RichWeber committed
224

225 226
В даному розділі ви випробували кожну частину шаблона проектування MVC. Ви дізналися як створювати класи моделей 
для опрацювання і перевірки даних вказаних користувачем.
RichWeber committed
227

228 229
Також, ви дізналися як отримати дані від користувача і як їх відобразити тому ж користувачу. Ця задача може займати 
багато часу в процесі розробки. Yii надає потужні віджети, які роблять задачу максимально простою.
RichWeber committed
230 231

В наступному розділі ви дізнаєтесь як працювати з базами даних, що необхідно в більшості додатків.