Laravelやってみる#6―バリデーションメッセージ

Laravel 7.x

ぬにょす(挨拶)。

表題の通りですが、PHPフレームワークであるところのLaravelを使ってみようということで、やったこと・できたこと・できなかったこと等を自分の備忘録として残していきます。

#6の今回はバリデーションのエラーメッセージを表示します。

やりたいこと

Laravelフレームワークにより、ログインフォームから送信したデータの検証が行われます。エラーがあれば、メッセージが返ってくるので、その内容を表示するようにします。

エラーメッセージの取得

デベロッパーツールで確認したところ、Laravelのバリデーションは以下のような形で返ってきました。

このエラーをログイン処理の中でキャッチします。

resources/js/views/LoginView.vue
  data: function() {
    return {
      form: {
        email: "",
        password: "",
        remember: false
      },
      errors: null
    };
  },
  methods: {
    login: function() {
      this.errors = null;
      axios
        .get("/airlock/csrf-cookie")
        .then(() => {
          axios
            .post("/login", this.form)
            .then(response => {
              this.$router.push({ name: "home" });
            })
            .catch(error => {
              if (error.response.status === 422) {
                this.errors = error.response.data.errors;
              } else {
                console.log("Login Error", error.response);
              }
            });
        })
        .catch(error => {
          console.log("Airlock Error", error);
        });
    }
  }

エラーメッセージの表示

取得したエラーメッセージを参照する算出プロパティ(computed)を用意し、Bootstrap-Vueのコンポーネントから呼び出します。

resources/js/views/LoginView.vue
<template>
  ...
                <b-row class="form-group">
                  <label for="email" class="col-md-4 col-form-label text-md-right">E-Mail Address</label>
                  <b-col md="6">
                    <b-input
                      v-model="form.email"
                      :state="emailError ? false : null"
                      type="email"
                      required
                      autocomplete="email"
                      autofocus
                    />
                    <b-form-invalid-feedback :state="!emailError">{{ emailError }}</b-form-invalid-feedback>
                  </b-col>
                </b-row>

                <b-row class="form-group">
                  <label for="password" class="col-md-4 col-form-label text-md-right">Password</label>
                  <b-col md="6">
                    <b-input
                      v-model="form.password"
                      :state="passwordError ? false : null"
                      type="password"
                      required
                      autocomplete="current-password"
                    />
                    <b-form-invalid-feedback :state="!passwordError">{{ passwordError }}</b-form-invalid-feedback>
                  </b-col>
                </b-row>
  ...
</template>

<script>
export default {
  computed: {
    emailError: function() {
      if (this.errors) {
        if (this.errors.email) {
          return this.errors.email[0];
        }
      }
      return "";
    },
    passwordError: function() {
      if (this.errors) {
        if (this.errors.password) {
          return this.errors.password[0];
        }
      }
      return "";
    }
  },
  ...

<b-input> の state プロパティは true, false, null を受け付けます。

Controls the validation state appearance of the component. ‘true’ for valid, ‘false’ for invalid’, or ‘null’ for no validation state

https://bootstrap-vue.js.org/docs/components/form-input#comp-ref-b-form-input-props

エラーメッセージがあれば state を false に設定し、なければ null に設定するようにしました。

<b-form-invalid-feedback> は state プロパティに false を設定した場合に可視状態になります。

When explicitly ‘false’, forces the feedback to show

https://bootstrap-vue.js.org/docs/components/form#comp-ref-b-form-invalid-feedback-props

ユーザー登録画面についても同様に変更しました。

resources/js/views/RegisterView.vue
<template>
  ...
                <b-row class="form-group">
                  <label for="name" class="col-md-4 col-form-label text-md-right">Name</label>
                  <b-col md="6">
                    <b-input
                      v-model="form.name"
                      :state="nameError ? false : null"
                      type="text"
                      required
                      autocomplete="name"
                      autofocus
                    />
                    <b-form-invalid-feedback :state="!nameError">{{ nameError }}</b-form-invalid-feedback>
                  </b-col>
                </b-row>

                <b-row class="form-group">
                  <label for="email" class="col-md-4 col-form-label text-md-right">E-Mail Address</label>
                  <b-col md="6">
                    <b-input
                      v-model="form.email"
                      :state="emailError ? false : null"
                      type="email"
                      required
                      autocomplete="email"
                    />
                    <b-form-invalid-feedback :state="!emailError">{{ emailError }}</b-form-invalid-feedback>
                  </b-col>
                </b-row>

                <b-row class="form-group">
                  <label for="password" class="col-md-4 col-form-label text-md-right">Password</label>
                  <b-col md="6">
                    <b-input
                      v-model="form.password"
                      :state="passwordError ? false : null"
                      type="password"
                      required
                      autocomplete="new-password"
                    />
                    <b-form-invalid-feedback :state="!passwordError">{{ passwordError }}</b-form-invalid-feedback>
                  </b-col>
                </b-row>
  ...
</template>

<script>
export default {
  computed: {
    nameError: function() {
      if (this.errors) {
        if (this.errors.name) {
          return this.errors.name[0];
        }
      }
      return "";
    },
    emailError: function() {
      if (this.errors) {
        if (this.errors.email) {
          return this.errors.email[0];
        }
      }
      return "";
    },
    passwordError: function() {
      if (this.errors) {
        if (this.errors.password) {
          return this.errors.password[0];
        }
      }
      return "";
    }
  },
  data: function() {
    return {
      form: {
        email: "",
        password: "",
        password_confirmation: ""
      },
      errors: null
    };
  },
  methods: {
    register: function() {
      axios
        .get("/airlock/csrf-cookie")
        .then(() => {
          axios
            .post("/register", this.form)
            .then(response => {
              this.$router.push({ name: "home" });
            })
            .catch(error => {
              if (error.response.status === 422) {
                this.errors = error.response.data.errors;
              } else {
                console.log("Register Error", error.response);
              }
            });
        })
        .catch(error => {
          console.log("Airlock Error", error);
        });
    }
  }
};
</script>

実行結果

メッセージの日本語化

知らぬ間にLaravel7.xドキュメントの日本語訳が登場していました。日本語ファイルを生成するコマンドもアップデートされているようなので実行してみましょう。

auth.php言語ファイル 7.x Laravel
php -r "copy('https://readouble.com/laravel/7.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
php -f install-ja-lang.php
php -r "unlink('install-ja-lang.php');"

resources/lang/ja に日本語ファイルが作成されました。念のため、英語ファイルとの差分を見てみると password.php の throttled だけ抜けてました。まぁパスワードリセット自体、ルートを閉じてしまったので見なかったことにしましょう(笑)。

無事にエラーメッセージが日本語化されました。

次回は

ナビゲーションバーの項目をログイン状態により切り替えます。

コメント

タイトルとURLをコピーしました