環境
// envのDB接続部を書き換えておく
php artisan migrate:fresh
composer require laravel/ui
php artisan ui vue --auth
npm install
npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
composer require laravel/pint --dev
npm run dev
php artisan serve
概要
以下記事の続きとして、バリデーションをかけていきます
Tips. エラーメッセージの日本語化
今回はバリデーションエラーのメッセージが多数表示されます
デフォルトで英語なので、日本語にしたい方は以下の記事を参照してください↓
1. テーブルとmodelの定義を変更する
カラム名 | |
---|---|
id | serial |
name | varchar(255) |
login_id | varchar(255) |
varchar(255) | |
password | varchar(255) |
created_at | timestamp |
updated_at | timestamp |
Indexes:
PRIMARY (id)
user_login_id_name_unique(login_id, name)
user_email_unique(email)
- nameのunique属性を外して、新しくlogin_idカラムを追加します
- そして、nameとlogin_id両方合わせたものに、unique属性を付与します
以下2つのmigrationファイルを追加・編集します
プロジェクトルート
php artisan make:migration edit_name_of_users_table --table=users
php artisan make:migration add_login_id_to_users_table --table=users
まずnameカラムの変更から
edit_name_of_users_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class EditNameOfUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->dropUnique(['name']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->unique(['name']);
});
}
}
編集後にphp artisan migrate
そしてlogin_idカラムとuniqueキーの追加をします
add_login_id_to_users_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddLoginIdToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('login_id');
$table->unique(['name', 'login_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropUnique(['name', 'login_id']);
});
}
}
編集後にphp artisan migrate
最後にmodelを編集します
- ホワイトリストにlogin_idを追加します
User.php
// ...
protected $fillable = [
'login_id',
'name',
'email',
'password',
];
// ...
2. 表示画面と登録・更新ロジックの修正
まずlogin_idの入力欄を追加し、passwordのrequiredを外します
home.blade.php
// ... login_idの入力欄を追加
<div class="row mb-3">
<label for="name"
class="col-md-4 col-form-label text-md-end">{{ __('ログインID') }}</label>
<div class="col-md-6">
<input v-model="login_id" id="login_id" type="text"
class="form-control @error('login_id') is-invalid @enderror" name="login_id"
required>
@error('login_id')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
// ... passwordのrequiredを外す
<input v-model="password" id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" @if (session('saved_user')) placeholder="更新が不要な場合は未入力にしてください" @endif>
// ... dataに追記
data: () => {
return {
login_id: '{{ old('login_id') ?? (session('saved_user')->login_id ?? '') }}',
// ... confirmメソッドに追記
} else {
console.log(this.login_id);
console.log(this.name);
次にロジックの修正をします
- login_idのデータを登録処理に追加します
- 単一のunique属性がemailについているので、登録処理のキーとなるカラムをemailに変更します
HomeController
$params = [
'login_id' => $request->login_id,
'name' => $request->name,
'email' => $request->email,
];
if ($request->password) {
$params['password'] = Hash::make($request->input(['password']));
}
DB::transaction(function () use ($request, $params) {
User::updateOrCreate([
'email' => $request->email,
], $params);
});
3. Requestの作成
まずリクエストファイルを作成します
- app/Http直下にRequestsフォルダが作成されます
プロジェクトルート
php artisan make:request Home/Store
次にControllerでuseします
- 既存のRequestは削除します
HomeController
namespace App\Http\Controllers;
use App\Models\User;
use App\Http\Requests\Home\StoreRequest;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
class HomeController extends Controller
// ...
public function store(StoreRequest $request)
{
最後にStoreRequestクラスのauthorizeメソッドの返り値をtrueに変更します
- これをtrueにすることでバリデーションが機能するようになります
StoreRequest.php
// ...
public function authorize()
{
return true;
}
// ...
4. ユニークバリデーション
まず基本的なバリデーションとemailのunique制限をかける
StoreRequest.php
public function rules(Request $request)
{
$rules = [
'login_id' => ['required', 'string', 'max:255'],
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email'],
'password' => ['nullable', 'required_if:email,null']
];
// 更新時の処理
if (empty($request->email) === false) {
$user = User::firstWhere('email', $request->email);
if (is_null($user) === false) {
$rules['password'] = [''];
}
}
return $rules;
}
※これでは不十分なので、少しづつ修正していきます
- login_idとname、2つのカラムに跨ったユニークバリデーションをかける
StoreRequest.php
$rules = [
'login_id' => ['required', 'string', 'max:255', Rule::unique('users')->where(function ($query) {
return $query->where('name', $request->name);
})],
'name' => ['required', 'string', 'max:255', Rule::unique('users')->where(function ($query) {
return $query->where('login_id', $request->login_id);
})],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email'],
'password' => ['required']
];
- uniqueメソッドにチェインしたwhereメソッドはクロージャを受け取ることができます
- そこで追加のクエリを記述すると、該当するデータに対してuniqueバリデーションをかけることができます
- 更新時にユニークバリデーションを外す
StoreRequest.php
// 更新時の処理
$user = User::firstWhere('email', $request->email);
if (is_null($user) === false) {
$rules['login_id'] = ['required', 'string', 'max:255', Rule::unique('users')->where(function ($query) use ($request) {
return $query->where('name', $request->name);
})->ignore($user),
];
$rules['name'] = ['required', 'string', 'max:255', Rule::unique('users')->where(function ($query) use ($request) {
return $query->where('login_id', $request->login_id);
})->ignore($user),
];
$rules['email'] = ['required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($user),
];
$rules['password'] = [''];
}
}
- ignoreメソッドをチェインすることで、引数のモデルから自動的にキーを取り出し、そのキーに合致するデータをuniqueバリデーションから除外します
end.Githubのリポジトリ
今回作成したアプリケーションは以下に公開しています↓