Model Binding と 1枚のBladeで CRUD する

1枚のBladeで確認画面付きCRUDを実現できると、Bladeの枚数が格段に少なくなって良さそう。
その前にまずModelBindingで単なるUserを1枚のBladeでCRUDしてみる。

1枚のBladeが複数の機能で使われることになり、Bladeの中に要素と制御が増えていくため、
実は、Bladeの枚数が増えたとしても1つのBladeを単純にした方が良いのかもしれないが、
1度作っておくとずっと使えるかもしれないので、そこまでやってみる。

やること

Laravelに最初から付いてくるUserを使って、name,email,passwordのCRUDをする。
URL(route)は以下。showのパラメタをOptionalにして、あればUpdate、なければCreateする。
Update、Createは、本質的に分けるべきと考えてURLを別にしてある。
firstOrNew()を使うと、あればUserインスタンスを読み込んでくれる。
なければインスタンスを作る。ただしレコードは作らない。新規作成操作時にレコードを作成する。


<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/


Route::get('/user/{user?}','UserController@show');
Route::post('/user/','UserController@add')->name('postAddUser');
Route::post('/user/{user}','UserController@edit')->name('postEditUser');

コントローラ

コントローラは以下。無条件に保存するだけなのでほとんど何も書いてない。
条件が増えてくるとそれなりに行数が増える。
ModelBindingの良さは、タイプヒンティングでEloquentのインスタンスを受けられること。
変数を受けてEloquentインスタンスを探す手間がバッサリ無い。

RequestValidatorは載せていません。


<?php

namespace App\Http\Controllers;

use App\Http\Requests\AddUserRequest;
use App\Http\Requests\EditUserRequest;
use App\User;

class UserController extends Controller
{
    public function show($id=null)
    {
        $user = User::firstOrNew(['id'=>$id]);
        return view('user',compact('user'));
    }

    public function add(User $user,AddUserRequest $request)
    {
        $user->fill($request->only(['name','email','password']))->save();
        return view('user',compact('user'));
    }

    public function edit(User $user,EditUserRequest $request)
    {
        $user->fill($request->only(['name','email','password']))->save();
        return view('user',compact('user'));
    }
}

Blade

肝心のBladeは以下。これだけなのに結構書かないといけない。

laravelcollective/htmlは大分前にLaravelから外れていて、使わない方が良いのかも。
自力でHTMLを書くのと大して労力が変わらない可能性がある。

結構書かないといけないから1枚にしたいのか、複数枚でよければあまり書かなくて良いのか、
微妙なところ。Laravel5.7なのでBootstrap4。validation用のクラスが全然違う。
親Blade(layouts.app)は何でも良いので載せていません。


@extends('layouts.app')
@section('content')
    

@if (isset($user->id))編集 @else 追加 @endif

@if ($user->wasRecentlyCreated) {!! Form::model($user,['route'=>['postEditUser',$user->id],'class'=>'form-horizontal'])!!} @else {!! Form::model($user,['route'=>['postAddUser'],'class'=>'form-horizontal'])!!} @endif
{!! Form::label('name', '名前 :') !!} @if($errors->has('name')) {!! Form::text('name',$user->name,['class'=>'form-control is-invalid']) !!} @else {!! Form::text('name',$user->name,['class'=>'form-control']) !!} @endif
{!! $errors->first('name') !!}
{!! Form::label('email', 'email :') !!} @if($errors->has('email')) {!! Form::email('email',$user->email,['class'=>'form-control is-invalid']) !!} @else {!! Form::email('email',$user->email,['class'=>'form-control']) !!} @endif
{!! $errors->first('email') !!}
{!! Form::label('password', 'password :') !!} @if($errors->has('password')) {!! Form::password('password',['class'=>'form-control is-invalid']) !!} @else {!! Form::password('password',['class'=>'form-control']) !!} @endif
{!! $errors->first('password') !!}
@if($user->wasRecentlyCreated) {!! Form::submit('保存',['class'=>'btn btn-primary form-control col-sm-2']) !!} @else {!! Form::submit('新規作成',['class'=>'btn btn-primary form-control col-sm-2']) !!} @endif
{!! Form::close() !!} @endsection

まとめ

relationもないし懸案の確認画面もないので、単純。
次回、has a、has many relation版と、確認画面付きの版を試します。