start-forms.md 12.1 KB
Newer Older
Anton A committed
1
Работа с формами
2
================
Anton A committed
3

4 5
В данном разделе мы обсудим получение данных от пользователя. На странице будет располагаться форма с полями для ввода
имени и email. Полученные данные будут показаны на странице для их подтверждения.
Anton A committed
6

7 8
Чтобы достичь этой цели, помимо создания [действия](structure-controllers.md) и двух [представлений](structure-views.md)
вы создадите [модель](structure-models.md).
Anton A committed
9

10
В данном руководстве вы изучите:
Anton A committed
11

12 13 14
* Как создать [модель](structure-models.md) для данных, введённых пользователем;
* Как объявить правила проверки введённых данных;
* Как создать HTML форму в [представлении](structure-views.md).
Anton A committed
15 16


17 18
Создание модели <a name="creating-model"></a>
---------------------------------------------
Anton A committed
19

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

```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'],
        ];
    }
}
```

46 47
Данный класс расширяет класс [[yii\base\Model]], который является частью фреймворка и обычно используется для работы
с данными форм.
Anton A committed
48

49 50 51
Класс содержит 2 публичных свойства `name` и `email`, которые используются для хранения данных, введённых пользователем.
Он также содержит метод `rules()`, который возвращает набор правил проверки данных. Правила, объявленные в коде выше
означают следующее:
Anton A committed
52

53 54
* Поля `name` и `email` обязательны для заполнения;
* В поле `email` должен быть правильный адрес email.
Anton A committed
55

56 57 58
Если объект `EntryForm` заполнен пользовательскими данными, то для их проверки вы можете вызвать метод
[[yii\base\Model::validate()|validate()]]. В случае неудачной проверки свойство [[yii\base\Model::hasErrors|hasErrors]]
станет равным `true`. С помощью [[yii\base\Model::getErrors|errors]] можно узнать, какие именно ошибки возникли.
Anton A committed
59 60


61 62
Создание действия <a name="creating-action"></a>
------------------------------------------------
Anton A committed
63

64
Далее создайте действие `entry` в контроллере `site`, точно так же, как вы делали это ранее.
Anton A committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

```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()) {
84
            // данные в $model удачно проверены
Anton A committed
85

86 87
            // делаем что-то полезное с $model ...
 
Anton A committed
88 89
            return $this->render('entry-confirm', ['model' => $model]);
        } else {
Alexander Makarov committed
90
            // либо страница отображается первый раз, либо есть ошибка в данных
Anton A committed
91 92 93 94 95 96 97
            return $this->render('entry', ['model' => $model]);
        }
    }
}
```

Действие создает объект `EntryForm`. Затем оно пытается заполнить модель данными из массива `$_POST`, доступ
98 99
к которому обеспечивает Yii при помощи [[yii\web\Request::post()]]. Если модель успешно заполнена, то есть пользователь
отправил данные из HTML формы, то для проверки данных будет вызван метод [[yii\base\Model::validate()|validate()]].
Anton A committed
100

101 102 103
Если всё в порядке, действие отобразит представление `entry-confirm`, которое показывает пользователю введенные им данные.
В противном случае будет отображено представление `entry`, которое содержит HTML форму и ошибки проверки данных, если
они есть.
Anton A committed
104

105 106 107 108
> Информация: `Yii::$app` представляет собой глобально доступный экземпляр-одиночку
[приложения](structure-applications.md) (singleton). Одновременно это [Service Locator](concept-service-locator.md),
дающий доступ к компонентам вроде `request`, `response`, `db` и так далее. В коде выше для доступа к данным из `$_POST`
был использован компонент `request`.
Anton A committed
109 110


111 112
Создание представления <a name="creating-views"></a>
----------------------------------------------------
Anton A committed
113

114 115
В заключение, создаём два представления с именами `entry-confirm` и `entry`, которые отображаются действием `entry` из
предыдущего подраздела.
Anton A committed
116

117
Представление `entry-confirm` просто отображает имя и email. Оно должно быть сохранено в файле `views/site/entry-confirm.php`.
Anton A committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

```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(); ?>
```

151 152 153 154
Для построения HTML формы представление использует мощный [виджет](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]].
Методы `begin()` и `end()` выводят открывающий и закрывающий теги формы. Между этими вызовами создаются поля ввода при
помощи метода [[yii\widgets\ActiveForm::field()|field()]]. Первым идёт поле для "name", вторым — для "email".
Далее для генерации кнопки отправки данных вызывается метод [[yii\helpers\Html::submitButton()]].
Anton A committed
155 156 157


Попробуем <a name="trying-it-out"></a>
158
--------------------------------------
Anton A committed
159

160
Чтобы увидеть всё созданное в работе, откройте в браузере следующий URL:
Anton A committed
161 162 163 164 165

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

166 167 168
Вы увидите страницу с формой и двумя полями для ввода. Перед каждым полем имеется подпись, которая указывает, какую
информацию следует вводить. Если вы нажмёте на кнопку отправки без ввода данных или если вы введете email в неверном
формате, вы увидите сообщение с ошибкой рядом с каждым проблемным полем.
Anton A committed
169

170
![Форма с ошибками](images/start-form-validation.png)
Anton A committed
171 172 173

После ввода верных данных и их отправки, вы увидите страницу с данными, которые вы только что ввели.

174
![Подтверждение введённых данных](images/start-entry-confirmation.png)
Anton A committed
175 176 177



178
### Как работает вся эта «магия» <a name="magic-explained"></a>
Anton A committed
179

180 181 182
Вы, скорее всего, задаётесь вопросом о том, как же эта HTML форма работает на самом деле. Весь процесс может показаться
немного волшебным: то как показываются подписи к полям, ошибки проверки данных при некорректном вводе и то что всё это
происходит без перезагрузки страницы.
Anton A committed
183

184 185 186 187 188
Да, проверка данных на самом деле происходит и на стороне клиента при помощи JavaScript и на стороне сервера.
[[yii\widgets\ActiveForm]] достаточно продуман, чтобы взять правила проверки, которые вы объявили в `EntryForm`,
преобразовать их в JavaScript код и использовать его для проведения проверок. На случай отключения JavaScript в браузере
валидация проводится и на стороне сервера как показано в методе `actionEntry()`. Это даёт уверенность в том, что данные
корректны при любых обстоятельствах.
Anton A committed
189

190 191
Подписи для полей генерируются методом `field()`, на основе имён свойств модели. Например, подпись `Name` генерируется
для свойства `name`. Вы можете модифицировать подписи следующим образом:
Anton A committed
192 193

```php
Anton A committed
194 195
<?= $form->field($model, 'name')->label('Ваше имя') ?>
<?= $form->field($model, 'email')->label('Ваш Email') ?>
Anton A committed
196 197
```

198 199 200
> Информация: В Yii есть множество виджетов, позволяющих быстро строить сложные и динамичные представления.
  Как вы узнаете позже, разрабатывать новые виджеты очень просто. Многое из представлений можно вынести в виджеты, чтобы
  использовать это повторно в других местах и упростить тем самым разработку в будущем.
Anton A committed
201 202

Резюме <a name="summary"></a>
203 204 205 206
-----------------------------

В данном разделе вы попробовали каждую часть шаблона проектирования MVC. Вы изучили как создавать классы моделей
для обработки и проверки пользовательских данных.
Anton A committed
207

208 209
Также, вы изучили как получать данные от пользователя и как показать данные пользователю. Это задача может занимать в
процессе разработки значительное время. Yii предоставляет мощные виджеты, которые делают задачу максимально простой.
Anton A committed
210

211
В следующем разделе вы изучите как работать с базами данных, что требуется в большинстве приложений.
Anton A committed
212