Laravel5.5: usersのCRUD機能を実装する

  • 1
    いいね
  • 0
    コメント

usersテーブルに関するCRUD機能を実装します。

親記事

Laravel 5.5で基本的なCRUDを作る - Qiita

usersのEloquentモデルを生成する

:link: モデル定義

usersテーブルの場合は、app/User.phpが既に存在するのでモデル生成は不要です。

usersのコントローラーを生成する

:link: リソースコントローラ

今回は、典型的なCRUD機能を提供してくれるリソースコントローラを利用させてもらいます。

PowerShell
> php artisan make:controller UserController --resource

app/Http/Controllers/UserController.phpが生成され、CRUDに関するアクションメソッドも自動で定義されています。
あとは中身の処理を書くだけです。

ルーティングを設定する

routes/web.php
Route::resource('users', 'UserController');

上の一行で、下記のようにCRUDに関するルートがまとめて設定されます。

動詞 URI アクション ルート名
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT/PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy

Artisanコマンドでルートの設定を確認することもできます。

PowerShell
> php artisan route:list

Eloquentモデルをインポートする

コントローラ内で頻繁に使うことになるので、モデルをインポートしておきます。

app/Http/Controllers/UserController.php
 use Illuminate\Http\Request;
+use App\User;

 class UserController extends Controller
 {

次からは、CRUDの機能をひとつひとつ実装していきます。

index

:link: モデルの取得

ユーザーを一覧表示します。
以前の記事で生成したデータが表示されます。
001.png

コントローラ

app/Http/Controllers/UserController.php
    public function index()
    {
        $users = User::all();
        return view('users.index', ['users' => $users]);
    }

ビュー

以前の記事で作ったレイアウトを利用します。

resources/views/users/index.blade.php
@php
    $title = __('Users');
@endphp
@extends('layouts.my')
@section('content')
<h1>{{ $title }}</h1>
<div class="table-responsive">
    <table class="table table-striped">
        <thead>
            <tr>
                <th>{{ __('ID') }}</th>
                <th>{{ __('Name') }}</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($users as $user)
                <tr>
                    <td>{{ $user->id }}</td>
                    <td><a href="{{ url('users/'.$user->id) }}">{{ $user->name }}</a></td>
                </tr>
            @endforeach
        </tbody>
    </table>
</div>
@endsection

手軽に見栄えを整えるためにBootstrapを利用しています。
また、後で多言語化に対応させるので、あらかじめ__メソッド内に文章を記述するようにしています。
:link: 翻訳文字列の取得

-    Name
+    {{ __('Name') }}

show

:link: 1モデル/集計の取得

1件だけを表示します。
002.png

コントローラ

app/Http/Controllers/UserController.php
    public function show(User $user)
    {
        return view('users.show', ['user' => $user]);
    }

「モデル結合ルート」を利用して簡潔に記述するため、showメソッドの引数は$idではなくUser $userとします。
:link: モデル結合ルート (Route Model Binding)

ビュー

resources/views/users/show.blade.php
@php
    $title = __('User') . ': ' . $user->name;
@endphp
@extends('layouts.my')
@section('content')
<h1>{{ $title }}</h1>

<!-- 編集・削除ボタン -->
<div>
    <a href="{{ url('users/'.$user->id.'/edit') }}" class="btn btn-primary">
        {{ __('Edit') }}
    </a>
    <!-- 削除ボタンは後で正式なものに置き換えます -->
    <a href="#" class="btn btn-danger">
        {{ __('Delete') }}
    </a>
</div>

<!-- ユーザー1件の情報 -->
<dl class="row">
    <dt class="col-md-2">{{ __('ID') }}</dt>
    <dd class="col-md-10">{{ $user->id }}</dd>
    <dt class="col-md-2">{{ __('Name') }}</dt>
    <dd class="col-md-10">{{ $user->name }}</dd>
    <dt class="col-md-2">{{ __('Email') }}</dt>
    <dd class="col-md-10">{{ $user->email }}</dd>
</dl>
@endsection

create, store

:link: Inserts

1件を新規追加します。
後でバリデーション・ルールを設定するまでは、パスワードの2回入力による確認は機能しません。
090.png

コントローラ

app/Http/Controllers/UserController.php
    // 追加用のフォーム画面へ移動
    public function create()
    {
        return view('users.create');
    }

    // 実際の追加処理
    // 終わったら、作ったばかりのユーザーのページへ移動
    public function store(Request $request)
    {
        $user = new User;
        $user->name = $request->name;
        $user->email = $request->email;
        $user->password = $request->password;
        $user->save();
        return redirect('users/'.$user->id);
    }

ビュー

resources/views/users/create.blade.php
@php
    $title = __('Create User');
@endphp
@extends('layouts.my')
@section('content')
<h1>{{ $title }}</h1>
<form action="{{ url('users') }}" method="post">
    {{ csrf_field() }}
    {{ method_field('POST') }}
    <div class="form-group">
        <label for="name">{{ __('Name') }}</label>
        <input id="name" type="text" class="form-control" name="name" required autofocus>
    </div>
    <div class="form-group">
        <label for="email">{{ __('Email') }}</label>
        <input id="email" type="email" class="form-control" name="email" required>
    </div>
    <div class="form-group">
        <label for="password">{{ __('Password') }}</label>
        <input id="password" type="password" class="form-control" name="password" required>
    </div>
    <div class="form-group">
        <label for="password_confirmation">{{ __('Confirm Password') }}</label>
        <input id="password_confirmation" type="password" class="form-control" name="password_confirmation" required>
    </div>
    <button type="submit" name="submit" class="btn btn-primary">{{ __('Submit') }}</button>
</form>
@endsection

:link: CSRF保護
:link: 疑似フォームメソッド

edit, update

:link: Updates

1件を更新します。
今のところ、メールアドレスとパスワードは変更できません。
010.png

コントローラ

app/Http/Controllers/UserController.php
    // 更新用フォーム画面へ移動
    public function edit(User $user)
    {
        return view('users.edit', ['user' => $user]);
    }

    // 実際の更新処理
    // 終わったら、そのユーザのページへ移動
    public function update(Request $request, User $user)
    {
        $user->name = $request->name;
        $user->save();
        return redirect('users/'.$user->id);
    }

ビュー

method_field()PUTを指定する以外はcreate.blade.phpと同じです。

resources/views/users/edit.blade.php
@php
    $title = __('Edit').': '.$user->name;
@endphp
@extends('layouts.my')
@section('content')
<h1>{{ $title }}</h1>
<form action="{{ url('users/'.$user->id) }}" method="post">
    {{ csrf_field() }}
    {{ method_field('PUT') }}
    <div class="form-group">
        <label for="name">{{ __('Name') }}</label>
        <input id="name" type="text" class="form-control" name="name" value="{{ $user->name }}" required autofocus>
    </div>
    <button type="submit" name="submit" class="btn btn-success">{{ __('Submit') }}</button>
</form>
@endsection

destroy

:link: モデル削除

1件を削除します。
現時点では、確認も何もなくいきなり削除します。

コントローラ

app/Http/Controllers/UserController.php
    public function destroy(User $user)
    {
        $user->delete();
        return redirect('users');
    }

ビュー

削除ボタンはあちこちで使うので、コンポーネントとしてまとめます。
:link: コンポーネントとスロット

resources/views/components/btn-del.blade.php
<form style="display:inline" action="{{ url($table.'/'.$id) }}" method="post">
    {{ csrf_field() }}
    {{ method_field('DELETE') }}
    <button type="submit" class="btn btn-danger">
        {{ __('Delete') }}
    </button>
</form>

先ほど作ったshowページの削除ボタンと置き換えます。

resources/views/users/show.blade.php
-    <a href="#" class="btn btn-danger">
-        {{ __('Delete') }}
-    </a>
+    @component('components.btn-del')
+        @slot('table', 'users')
+        @slot('id', $user->id)
+    @endcomponent

完了

ログインもバリデーションもありませんが、とりあえずCRUDの根幹はできあがりました。