@jazzus

Как показать ошибки в Vue от Laravel Request?

Цель - отправить данные с формы и при ошибках валидации вывести ее на экран c использованием Laravel Request.

Создал файл валидации ListRequest командой php artisan make:request. Содержание файла:
public function rules()
    {
        return [
          'name' => 'required|string|max:50|unique',
        ];
    }

    public function messages()
    {
        return [
          'name.required' => 'Поле обязательно для заполнения',
          'name.max' => 'Не менее 50 символов',


Соответственно при записи формы в контроллере, теперь за проверку отвечает ListRequest:
public function store(ListRequest $request)

Следующий шаг - нужно получить сообщения ошибок из файла ListRequest во VUE. Как это сделать?

В blade шаблонах Laravel получал сообщения ошибок через переменную errors (куда Laravel автоматом записывает сообщения, которые не прошли проверку через файл ListRequest):
@if (count($errors) > 0)
    <div class="alert alert-danger" style="text-align: center;" role="alert">
      @foreach ($errors->all() as $error)
       <b> {{ $error }}</b><br>
      @endforeach
    </div>
@endif


Как получить эти сообщения в VUE? Максимум чего добился это вывод данных сообщений в консоли через код:
.catch(function (error) {
                  console.log(error.response.data);


В интернете нашел много вариантов с валидацией в контроллере и записью ошибок в json, но я бы не хотел в контроллерах устраивать валидации, когда есть отдельный файл для валидации с сообщениями об ошибках в глобальной переменной от Laravel errors (т.е. как в моем примере). Как сообщения из errors получить в VUE?
  • Вопрос задан
  • 292 просмотра
Решения вопроса 1
Вам нужно валидировать ваши данные, которые приходят от клиента.
public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');

        $validator = \Validator::make($credentials, [
          'email' => 'required',
          'password' => 'required',
        ]);

        if ($validator->fails()) {
          return response()
            ->json(['errors' => $validator->errors()], 422);
        }
....
}


Код:
if ($validator->fails()) {
          return response()
            ->json(['errors' => $validator->errors()], 422);
        }

Вернет клиенту (в случае ошибки), массив errors, со всеми ошибками, которые возникли.

У меня это работает так: в Login.vue есть метод, который авторизует пользователя:

login(){
        var app = this
        var user = this.$auth.login({
            params: {
              email: app.email,
              password: app.password
            },
            success: function () {
              this.$store.dispatch('authuser/loadUserData');
            },
            error: function (err) {
              app.errors = err.response.data.errors;
            },
            rememberMe: app.remember,
            redirect: '/',
            fetchUser: true,
        });
      },

data(){
      return {
        email: null,
        password: null,
        errors: {},
        remember: true
      }
    },

Собственно, если мы получили ошибку, то:
error: function (err) {
              app.errors = err.response.data.errors;
            },
добавляем ошибки в массив ошибок, далее этот массив просто выводим:

<div v-if="errors" v-for="category in errors">
                <div class="m-alert m-alert--outline alert alert-danger alert-dismissible" role="alert" v-for="error in category">
                  <span>{{ error }}</span>
                </div>
              </div>

Тут два цикла, так как массив errors из ответа, будет содержать элементы: errors_password, errors_email и тд, каждый из которых является массивом. Но это вы уже сами можете в ответе сервера посмотреть.

На всякий случай прикрепляю полный файл Login.vue:
Login.vue
<template>
  <!-- begin:: Page -->
  <div class="m-grid m-grid--hor m-grid--root m-page">
    <div class="m-grid__item m-grid__item--fluid m-grid m-grid--hor m-login m-login--signin m-login--2 m-login-2--skin-2" id="m_login" style="background-image: url(/assets/app/media/img//bg/bg-3.jpg);">


      <div class="m-grid__item m-grid__item--fluid	m-login__wrapper">
        <div class="m-login__container">
          <div class="m-login__logo">
            <a href="#">
              <img src="/assets/demo/demo7/media/img/logo/logo.svg" style="height:70px;">
            </a>
          </div>
          <div class="m-login__signin">
            <div class="m-login__head">
              <h3 class="m-login__title">
                Авторизация
              </h3>
              <div class="m-login__desc">
                Заполните данные ниже для авторизации:
              </div>
            </div>
            <form class="m-login__form m-form" autocomplete="off" @submit.prevent="login" method="post">

              <div v-if="errors" v-for="category in errors">
                <div class="m-alert m-alert--outline alert alert-danger alert-dismissible" role="alert" v-for="error in category">
                  <span>{{ error }}</span>
                </div>
              </div>


              <div class="form-group m-form__group">
                <input type="email" id="email" class="form-control" placeholder="E-mail" v-model="email" required autofocus>
              </div>

              <div class="form-group m-form__group">
                <input type="password" id="password" class="form-control" v-model="password" placeholder="Пароль" equired>
              </div>
              <div class="row m-login__form-sub">
    						<div class="col m--align-left m-login__form-left">
    							<label class="m-checkbox  m-checkbox--focus m-checkbox--state-accent">
    							<input type="checkbox" name="remember" v-model="remember" checked="checked"> Запомнить меня
    							<span></span>
    							</label>
    						</div>
    						<div class="col m--align-right m-login__form-right">
    							<router-link :to="{ name: 'register'}" id="m_login_forget_password" class="m-link">Забыли пароль?</router-link>
    						</div>
    					</div>

              <div class="m-login__form-action">
                <button type="submit" class="btn btn-accent m-btn m-btn--pill m-btn--custom m-btn--air  m-login__btn">Авторизоваться</button>
              </div>


            </form>
          </div>
          <div class="m-login__account">
            <span class="m-login__account-msg">
            У вас еще нет аккаунта?
            </span>&nbsp;&nbsp;
            <router-link :to="{ name: 'register'}" class="m-link m-link--light m-login__account-link" style="border-bottom: 1px solid #6a6279;">
              Зарегистировать аккаунт
            </router-link>
          </div>

          <div class="m-login__forget-password">
            <div class="m-login__head">
              <h3 class="m-login__title">
                Забыли пароль?
              </h3>
              <div class="m-login__desc">
                Укажите Ваш e-mail для восстановления пароля:
              </div>
            </div>
            <form class="m-login__form m-form" action="">
              <div class="form-group m-form__group">
                <input class="form-control m-input" type="text" placeholder="Email" name="email" id="m_email" autocomplete="off">
              </div>
              <div class="m-login__form-action">
                <button id="m_login_forget_password_submit" class="btn btn-focus m-btn m-btn--pill m-btn--custom m-btn--air  m-login__btn m-login__btn--primaryr">
                  Выслать новый
                </button>
                &nbsp;&nbsp;
                <button id="m_login_forget_password_cancel" class="btn btn-outline-focus m-btn m-btn--pill m-btn--custom m-login__btn">
                  Отмена
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- end:: Page -->

</template>

<script>
  import { mapState, mapActions } from 'vuex';
  export default {
    data(){
      return {
        email: null,
        password: null,
        errors: {},
        remember: true
      }
    },
    computed: mapState({
      user: state => state.authuser.user
    }),
    methods: {
      login(){
        var app = this
        var user = this.$auth.login({
            params: {
              email: app.email,
              password: app.password
            },
            success: function () {
              this.$store.dispatch('authuser/loadUserData');
            },
            error: function (err) {
              app.errors = err.response.data.errors;
            },
            rememberMe: app.remember,
            redirect: '/',
            fetchUser: true,
        });
      },

    }
  }
</script>
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@mykolaim
PHP developer
Когда Request не проходит валидацию вам на фронт придет http код 422 и список ошибок в массиве errors в формате JSON, к примеру:
{
  "errors": [
    {
      "field": "username",
      "message": "The username has already been taken."
    }
  ]
}


Соответсвенно вам нужно парсить этот json и для каждой ошибки предпринимать те или инные действия.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
WayToStart Москва
от 40 000 до 80 000 руб.
Супердок Санкт-Петербург
от 100 000 до 120 000 руб.