環境
- Laravel: 8.6.2
- Vue.js: 2.6.12
- PHP: 8.0.8
- Composer: 2.5.1
- Node.js: 19.3.0
// 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
概要
- 管理ユーザーが任意のユーザーを作成・更新できるアプリケーションを作成します
- Userの登録・更新処理を題材に、Controller -> vue -> bladeとデータを渡していきます
1. テーブルを書き換える
- id,name,email,timestampsのシンプルなテーブルを作成します
- 既存のusersテーブルから余分なものを削除して、nameにunique属性を付与します
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
2. 表示画面を作る
既存のhome.blade.phpを改変する形で実装します
(機能的にはRegister画面と同じことをします)
※個々のbladeファイルに個別のvueを適用させる方法は以下の記事で↓
- まずRoutingを書き換えます
// ...
Route::post('/store', [App\Http\Controllers\HomeController::class, 'store'])->name('store');
- 次に登録画面を作成します
- 画面レイアウトはhome.blade.phpを、入力欄はauth/login.phpを踏襲します
- 登録処理にscriptは何ら影響を及ぼしませんが、更新時に必要なので、動作確認用にscriptを記載します
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">登録・更新</div>
<div class="card-body">
<form method="POST" action="{{ route('store') }}">
@csrf
{{-- 名前 --}}
<div class="row mb-3">
<label for="name"
class="col-md-4 col-form-label text-md-end">{{ __('名前') }}</label>
<div class="col-md-6">
<input v-model="name" id="name" type="text"
class="form-control @error('name') is-invalid @enderror" name="name" required>
@error('name')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
{{-- メールアドレス --}}
<div class="row mb-3">
<label for="email"
class="col-md-4 col-form-label text-md-end">{{ __('メールアドレス') }}</label>
<div class="col-md-6">
<input v-model="email" id="email" type="email"
class="form-control @error('email') is-invalid @enderror" name="email" required>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
{{-- パスワード --}}
<div class="row mb-3">
<label for="email"
class="col-md-4 col-form-label text-md-end">{{ __('パスワード') }}</label>
<div class="col-md-6">
<input v-model="password" id="password" type="password"
class="form-control @error('password') is-invalid @enderror" name="password" required>
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<button type="submit" @click="confirm">登録</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('js')
<script>
const app = new Vue({
el: '#app',
data: () => {
return {
name: '',
email: '',
password: '',
}
},
methods: {
confirm: function(e) {
if (confirm('登録しますか?')) {
return true;
} else {
console.log(this.name);
console.log(this.email);
console.log(this.password);
e.preventDefault();
return false;
}
}
}
});
</script>
@endsection
3. 登録・更新処理を作る
- まずHomeController.phpに登録処理(storeメソッド)を記述します
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
// $this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
}
public function store(Request $request)
{
DB::transaction(function () use ($request) {
User::create([
'name' => $request->input(['name']),
'email' => $request->input(['email']),
'password' => Hash::make($request->input(['password'])),
]);
});
return redirect()->route('home');
}
}
usersテーブルを確認してみてください
入力したuserが登録されていればOKです!
- 次にupdateOrCreateメソッドを使用した形に書き換える
更新時はパスワードを任意入力にしたいので、全体的に変更を加えます
// ...
public function store(Request $request)
{
$params = [
'name' => $request->name,
'email' => $request->email,
];
if ($request->password) {
$params['password'] = Hash::make($request->input(['password']));
}
DB::transaction(function () use ($request, $params) {
User::updateOrCreate([
'name' => $request->name,
], $params);
});
return redirect()->route('home');
}
updateOrCreateメソッドを使用することで、入力されたnameと同じnameを持つデータが既にDBにある場合は更新処理、なければ新規登録処理になります
1の新規登録処理で入力したデータと、name以外が違う入力値で登録ボタンを押した後、DBの値が更新されていればOKです!
- 登録・更新したユーザーの情報を持たせて、元の画面に遷移させる
updateOrCreateメソッドの条件にnameを使用しているので同様に、nameを元に直近で操作したUserを引っ張ってきます
// ...
$saved_user = User::firstWhere('name', $request->input(['name']));
$status = 'ユーザー情報の登録に成功しました!';
return redirect()->route('home')->with(compact('saved_user', 'status'));
4. 更新画面用にscriptを修正する
vueのデータにControllerから値を渡します
<script>
// ...
name: '{{ old('name') ?? (session('saved_user')->name ?? '') }}',
email: '{{ old('email') ?? (session('saved_user')->email ?? '') }}',
password: '{{ old('password') ?? '' }}',
// ...
</script>
最後にパスワードのplaceholderをセットします
// ...
<input v-model="password" id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" @if(session('saved_user')) placeholder="更新が不要な場合は未入力にしてください" @endif required>
// ...
以上でひとまず完了となります!
バリデーションについて
ここまでの実装で、一点不十分な点があります
お分かりの方もいらっしゃるかと思いますが、passwordのrequiredです
「更新時は未入力にしてください」となっていますが、このままの状態では未入力が許されません
この問題を解決するのが、バックエンド側でのバリデーションです
以下の記事で、このアプリケーションを拡張させた形でバリデーションを実装していきます↓
準備中
end. Githubのリポジトリ
今回作成したアプリケーションのリポジトリです↓