Может войдёшь?
Черновики Написать статью Профиль

Основы Laravel 5: Запросы из форм и проверка ввода

перевод Основы Laravel 5 Laracasts

Это перевод видео-урока с Laracasts, серия Laravel 5 Fundamentals, урок №12Form Requests and Controller Validation от . Перевод обновлён . Опечатка? Выдели и нажми Ctrl+Enter.

(0:00)
Хорошо, мы готовы разобраться с валидацией, это довольно интересная тема. Так что если я перейду на PHPArticlesController — вот где мы закончили в прошлый раз. Единственное различие в том, что я добавил несколько документирующих комментариев в различные методы. И хорошо, если это станет и вашей привычкой. И, к счастью, если вы используете что-нибудь, наподобие PhpStorm, то этот процесс может быть автоматизирован. Хорошо, давайте пойдём в низ страницы, в метод PHPstore(). Вот на чём нам тут нужно сосредоточиться. Итак, если вы помните, эту форму в её текущем состоянии можно отправить, и это не вызовет ошибки.

(0:30)
Попробуем отправить её, и... новая запись была внесена в таблицу БД. И мы выводим её на экран, но там ничего нет. Это очень плохо. Итак, вместо этого мы используем валидацию, чтобы убедиться, что такого рода вещей больше не случится. Итак, давайте начнём разбираться прямо сейчас. Но для начала напишем:

sqlselect * from articles;

и я собираюсь также сделать

sqldelete from articles where id = 7;

Просто чтобы начать с нуля. Хорошо, давайте займёмся этим.

(1:00)
Сейчас я покажу вам два различных способа как с этим работать. Один способ — использовать нечто, что мы называем запросом для форм (класс и объект). Это действительно полезно для более сложных проверок. Но бывают и случаи где нужна очень простая валидация. Вы просто хотите убедиться, что пользователь заполнил одно-два поля, и что теперь вы можете идти дальше. И для таких ситуаций мы можем воспользоваться типажом (trait), который Laravel включает в себя по умолчанию. Итак, давайте начнём работу с запросами для форм. Как вы можете представить, у нас для этого есть генератор.

(1:30)
Итак, если я запущу:

shphp artisan

И мы прокрутим вверх, вы увидите тут раздел make:request. Считайте что эти классы — это способ для пользователя сделать какой-либо запрос к вашему приложению, например, регистрация, продление подписки, или в данном случае — создание новой статьи. Так почему бы нам это не попробовать? Сделаем новый запрос для формы, и мы могли бы назвать его PHPCreateArticle или PHPPublishArticle или PHPSchedule – любую терминологию, уместную для вашего приложения:

(2:00)

shphp artisan make:request CreateArticleRequest

В данном случае простого метода CRUD достаточно. Многие люди также добавляют тут в конце PHPRequest, как суффикс. Вы можете тоже так сделать или просто оставить как есть, тут всё зависит от ваших предпочтений. Мы его добавим. И вот теперь всё. Теперь мы переключимся обратно, и, если я открою app/HttpRequests, вот куда все те классы будут добавлены (CreateArticleRequest.php). Это выглядит немного путано, но, фактически, тут всё очень, очень просто.

(2:30)
Итак, у нас здесь два различных метода, PHPauthorize() и PHPrules(). Первый определяет, есть ли у пользователя разрешение выполнять такой тип запроса или действия? Вот пример. Что если кто-нибудь попытается отредактировать комментарий, который он сам не создавал? Конечно же, мы не хотим допускать этого. Джон не может редактировать комментарий, который создала Джейн. Тут (в методе PHPauthorize()) мы и можем добавлять такого типа логику. В нашем случае, у нас в приложении даже не настроена система регистрации и подписки.

(3:00)
Так что я просто установлю здесь PHPtrue:

PHP
return true;

Сейчас кто угодно может сделать этот запрос. Затем у нас есть наш метод PHPrules(). И здесь мы можем добавлять наши условия, по сути, для запроса. Например, если мы вернёмся к PHParticles/create, у нас есть заголовок (PHPtitle), тело (PHPbody) и дата публикации (PHPpublished_at). Хорошо, мы можем ссылаться на эти имена. Заголовок будет обязателен:

PHP
'title' => 'required',

Затем, тело статьи тоже будет обязательно для заполнения:

PHP
'body' => 'required',

и наша дата PHPpublished_at также будет обязательна:

PHP
'published_at' => 'required'

(3:30)
Но, возможно, есть и другие вещи, которые нам тут нужно сделать. Например, представьте, что у вас есть форма регистрации, и ваше поле электронной почты обязательно для заполнения, но оно также должно быть определённого типа. Оно должно походить на адрес электронной почты. И затем, возможно, ваше имя тоже обязательно, и оно должно быть длиной не менее 2 символов. И если вы хотите увидеть весь огромный список того, что вы можете делать, посетите эту страницу документации. Почему бы нам не добавить ещё парочку?

(4:00)
Мы могли бы либо использовать тут символ pipe (|), так что я мог бы написать

required|date

(тут также ожидается тип — дата)
Заметьте, что мы используем |, чтобы разделить их. Или, если вы предпочтёте иное, то можете использовать простой массив PHP['required''date']. Любой из вариантов сработает. Давайте оставим вариант с |. Далее, для заголовка, просто для интереса, скажем ему нужно быть длиной минимум 3 символа. Как тут нам быть? Я могу написать:

PHP
'title' => 'required|min:3',

то есть min: и затем минимальное значение. Рассматривайте это как наш аргумент.

(4:30)
В нашем случае, он должен быть длиной по крайней мере 3 символа, так что мы можем представить его таким образом. Хорошо, сейчас мы настроили авторизацию, а также наши правила для валидации данных, теперь давайте переключимся на наш контроллер, и сейчас всё, что нам нужно сделать – это ввести подсказку для ожидаемого типа данных в коде вот здесь:

PHP
public function store(Requests\CreateArticleRequest $request)

Здесь дадим имя PHP$request. Хорошо, таким образом, мы можем оставить тут всё как есть, или можем импортировать класс наверху и слегка подчистить код. Затем обновим наш комментарий.

(5:00)
Класс. Теперь вот очень важная для понимания концепция. Когда мы ввели подсказку ожидаемого типа нашего запроса (typehint) для форм, за кадром Laravel сообразит, что мы здесь занимаемся валидацией. И он автоматически запустит валидацию до того, как этот метод на самом деле начнёт выполняться. Это очень важно понять. Другими словами, это означает, что тело этого метода никогда не будет запускаться. Мы никогда не создадим статью, если только наша проверка не прошла.

(5:30)
Теперь что же произойдёт, если валидация завершилась неудачей? Например, если пользователь не ввёл ничего в поле заголовка, то проверка потерпит неудачу, этот метод никогда не запустится, и вместо этого мы на самом деле перенаправим его на предыдущую страницу, чтобы пользователь мог попробовать опять. ОК, давайте прежде чем проверить как всё работает в браузере, вместе пройдём весь этот цикл ещё один раз. Пользователь приходит на страницу create, заполняет различные поля формы.

(6:00)
Когда форма отправлена, мы готовимся запустить этот метод. Однако, Laravel понял тот факт, что мы задали подсказку формата типа данных для этого объекта, и он постарается сделать всё возможное, чтобы дать нам именно такой объект. Однако, в процессе он обнаружит, что этот объект может быть проверен, так что он автоматически запустит для вас всю валидацию. Если валидация прошла успешно, то нам даётся объект запроса, и статья создаётся. Однако, ещё раз, если проверка не прошла, то этот метод не будет срабатывать, а вместо этого мы перенаправляемся на предыдущий маршрут, чтобы пользователь мог исправить ошибку в форме.

(6:30)
Сейчас я хочу, чтобы вы отметили что мы реализовали проверку, не добавив ни единой строки в тело этого метода. Так что я удалю этот комментарий. Далее, мы получаем запрос, значит нам больше не нужно использовать фасад. Я могу просто сказать:

PHP
Article::create($request->all());

И это было бы эквивалентно. Что означает, что тут сверху мы также можем убрать вот этот импорт.

(7:00)
ОК, всё очень красиво. Итак, почему бы нам не попробовать теперь это в браузере и не посмотреть, сработает ли это? Мы идём в articles/create, и в этот раз мы введём данные. Так, Enter, Enter и текущая дата – всё ОК. Добавить статью, и всё сработало. Так что никаких вопросов там.
А в этот раз мы попробуем отправить форму, не заполнив что-либо. Давайте оставим тело пустым. Хорошо, сейчас, я добавляю статью, и давайте посмотрим.

(7:30)
Нас не перенаправили обратно на нашу главную страницу, а просто отправили обратно в эту же форму, потому что валидация потерпела неудачу. Так что, вот что я имею в виду, когда говорю, что это всё в некотором роде происходит автоматически, и это довольно круто. Но у нас есть одна проблема. Если пользователь совершил ошибку, мы его не известили, что же именно пошло не так, и у них на самом деле нет никакой подсказки, и, как вы можете себе представить, в большой форме, это будет проблемой. Нам нужно выдать какую-то обратную связь. Так почему бы нам это не исправить?

(8:00)
Мы можем сделать это, вернувшись к нашему представлению, и почему бы нам не показывать ошибки валидации прямо здесь под формой? И вот ещё одна вещь, которую важно понять. Ваши представления всегда будут иметь доступ к переменной ошибок PHP$errors. Чтобы продемонстрировать это, давайте сделаем так:

PHP
var_dump($errors)

Давайте посмотрим, что из этого выйдет. Итак, мы идём на страницу, и теперь вы можете видеть, что это набор ошибок. Нам не нужно было создавать эту переменную или передавать её в представление — всё это было автоматически сделано Laravel.

(8:30)
Но прямо сейчас здесь пусто, потому что у нас нет ошибок валидации. Но если мы запустим вот так, то смотрите что тут сейчас... Мы запустили проверку, она провалилась, нас перенаправили обратно, набор ошибок заполнился, и сейчас вы можете увидеть тут две ошибки. Итак, вот что мы можем сделать. Мы могли бы сказать:

PHP
@if ($errors->any())

Это всего лишь метод-помощник, который даёт нам знать, если у нас возникли какие-либо ошибки. Итак, если они есть (и мы закроем PHP@endif внизу), то мы хотим вывести их на экран.

(9:00)
Почему бы нам тут не использовать какие-нибудь классы Bootstrap:

<ul class="alert alert-danger">

Теперь, я могу сказать, если у нас есть какие-либо ошибки, то:

PHP
@foreach ($errors->all() as $error)

отобразить их как элементы списка вот так:

PHP
<li>{{ $error }}</li>

и затем наконец:

PHP
@endforeach

И мы закончили. Довольно легко. Итак, давайте попробуем сделать это ещё один раз. У нас нет ошибок, так что мы здесь ничего не показываем.

(9:30)
Но дальше, мы пытаемся отправить форму, и у нас есть ошибки, так что вы видите их в этом списке. И похоже наш CSS здесь слегка глючит, но вы поняли основную идею. Важный момент в том, что теперь пользователь получает какую-то обратную связь. Так что если мы, допустим, заполнили заголовок, но оставили тело пустым, давайте нажмём Add Article и теперь это работает. И заметьте, что сообщения являются динамичными. Итак, допустим, мы ввели тело и заголовок, то есть мы справились с правилом валидации required, но у нас недостаточно символов. Помните, мы установили минимальную длину?

(10:00)
Теперь, когда мы запускаем это, то проверка всё ещё будет терпеть неудачу, и сообщение будет обновлено соответствующим образом. Итак, ещё раз, давайте правильно отформатируем и опубликуем сегодня, и после того, как мы жмём кнопку чтобы добавить статью, всё сработало. Так что работать с проверками данных в Laravel достаточно просто. Но позвольте мне показать вам ещё одну последнюю штуку, чтобы завершить урок. Мы говорили о запросах для форм, которые довольно интересны. Они предлагают выделенное место, для размещения всего этого хозяйства. Однако, если вы не хотите напрягаться и создавать класс, то, как я говорил вам, мы также можем вызвать метод PHPvalidate() прямо в контроллере.

(10:30)
Позвольте мне показать вам, как это выглядит. Если мы посмотрим на родительский класс, то заметим, что мы импортируем типаж PHPValidatesRequests, и в частности, у нас есть метод PHPvalidate(), которому вы передаёте свой запрос и правила, и он, по сути, будет работать практически тем же образом. Так что давайте попробуем. В этот раз мы вернёмся сюда и сейчас, мы не будем использовать PHPCreateArticleRequest, мы просто используем обычный запрос Laravel — PHPRequest.

(11:00)
Позвольте я импортирую тут сверху, PHPIlluminate\Http\Request. Мы обновим наш комментарий (docblock), и теперь нам не нужен запрос для форм, мы можем просто вызвать PHPvalidate() прямо в контроллере. Мы передаём в метод PHP$request, это даст нам информацию, которую пользователь внёс в форму, и затем мы передаём наши правила проверки данных, в точности как мы делали раньше. Вот здесь. Итак, давайте сделаем всё попроще:

PHP
$this->validate($request, ['title' => 'required''body' => 'required']);

(11:30)
Как я и говорил, для простых вещей это довольно хороший способ. Он простой и быстрый. Хорошо, давайте попробуем этот способ вместе. Мы создадим новую статью, я оставлю заголовок и тело пустыми, и мы должны получить точно такой же результат, что и раньше. И точно, то же самое мы и получаем. Таким образом, вам решать, когда какой способ использовать. Если вы хотите, вы всегда можете использовать запрос для форм и никогда не вызывать этот метод PHPvalidate() в вашем контроллере. Некоторые люди сказали бы: «Контроллер не должен заниматься валидацией».

(12:00)
В самом деле? Опять же, всё просто зависит от контекста. Однако, круто, что вы можете самостоятельно принимать решение. Итак, что мы хотим сделать в этом случае? Поскольку мы уже создали PHPCreateFormRequest (оговорка: PHPCreateArticleRequestприм. пер.), мы отменим несколько строк кода и вернёмся к тому, что у нас было раньше. ОК, это всё выглядит хорошо. Хорошая работа. В следующем видео давайте вернёмся к нашим представлениям и поговорим немного о частичных шаблонах (partials) и том, как почистить и упростить наш код.

Как вы считаете, полезен ли этот материал? Да Нет

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.