@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?
  • Вопрос задан
  • 2203 просмотра
Решения вопроса 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 и для каждой ошибки предпринимать те или инные действия.
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы