1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】 Controller -> vue -> blade とデータを渡す

Last updated at Posted at 2022-12-30

環境

  • 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. テーブルを書き換える

  1. id,name,email,timestampsのシンプルなテーブルを作成します
    • 既存のusersテーブルから余分なものを削除して、nameにunique属性を付与します
create_users_table.php
<?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を適用させる方法は以下の記事で↓

  1. まずRoutingを書き換えます
route/web.php
// ...
Route::post('/store', [App\Http\Controllers\HomeController::class, 'store'])->name('store');
  1. 次に登録画面を作成します
    • 画面レイアウトはhome.blade.phpを、入力欄はauth/login.phpを踏襲します
    • 登録処理にscriptは何ら影響を及ぼしませんが、更新時に必要なので、動作確認用にscriptを記載します
home.blade.php
@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. 登録・更新処理を作る

  1. まずHomeController.phpに登録処理(storeメソッド)を記述します
HomeController.php
<?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です!

  1. 次にupdateOrCreateメソッドを使用した形に書き換える

更新時はパスワードを任意入力にしたいので、全体的に変更を加えます

HomeController.php
// ...
    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です!

  1. 登録・更新したユーザーの情報を持たせて、元の画面に遷移させる

updateOrCreateメソッドの条件にnameを使用しているので同様に、nameを元に直近で操作したUserを引っ張ってきます

HomeController.php
// ...
$saved_user = User::firstWhere('name', $request->input(['name']));
$status = 'ユーザー情報の登録に成功しました!';
return redirect()->route('home')->with(compact('saved_user', 'status'));

4. 更新画面用にscriptを修正する

vueのデータにControllerから値を渡します

home.blade.php
<script>
// ...
    name: '{{ old('name') ?? (session('saved_user')->name ?? '') }}',
    email: '{{ old('email') ?? (session('saved_user')->email ?? '') }}',
    password: '{{ old('password') ?? '' }}',
// ...
</script>

最後にパスワードのplaceholderをセットします

home.blade.php
// ...
<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のリポジトリ

今回作成したアプリケーションのリポジトリです↓

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?