144
139

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-05-27

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

親記事

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

usersのEloquentモデルを生成する

:link: readouble.com: モデル定義

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

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

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

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: readouble.com: モデルの取得

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

URL例: http://<APP_URL>/users
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')
<div class="container">
    <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>
</div>
@endsection

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

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

show

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

1件だけを表示します。

URL例: http://<APP_URL>/users/show/1
002.png

コントローラ

app/Http/Controllers/UserController.php
    /**
     * Display the specified resource.
     *
     * @param  \App\User $user
     * @return \Illuminate\Http\Response
     */
    public function show(User $user)
    {
        return view('users.show', ['user' => $user]);
    }

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

ビュー

resources/views/users/show.blade.php
@php
    $title = __('User') . ': ' . $user->name;
@endphp
@extends('layouts.my')
@section('content')
<div class="container">
    <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">{{ __('E-Mail Address') }}</dt>
        <dd class="col-md-10">{{ $user->email }}</dd>
    </dl>
</div>
@endsection

create, store

:link: readouble.com: Inserts

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

URL例: http://<APP_URL>/users/create
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')
<div class="container">
    <h1>{{ $title }}</h1>
    <form action="{{ url('users') }}" method="post">
        @csrf {{-- CSRF保護 --}}
        @method('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">{{ __('E-Mail Address') }}</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>
</div>
@endsection

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

edit, update

:link: readouble.com: Updates

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

URL例: http://<APP_URL>/users/2/edit
010.png

コントローラ

app/Http/Controllers/UserController.php
    // 更新用フォーム画面へ移動
    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\User $user
     * @return \Illuminate\Http\Response
     */
    public function edit(User $user)
    {
        return view('users.edit', ['user' => $user]);
    }

    // 実際の更新処理
    // 終わったら、そのユーザのページへ移動
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\User $user
     * @return \Illuminate\Http\Response
     */
    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')
<div class="container">
    <h1>{{ $title }}</h1>
    <form action="{{ url('users/'.$user->id) }}" method="post">
        @csrf
        @method('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-primary">{{ __('Submit') }}</button>
    </form>
</div>
@endsection

destroy

:link: readouble.com: モデル削除

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

コントローラ

app/Http/Controllers/UserController.php
    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\User $user
     * @return \Illuminate\Http\Response
     */
    public function destroy(User $user)
    {
        $user->delete();
        return redirect('users');
    }

ビュー

削除ボタンは色々な場所で使うので、コンポーネントとしてまとめておきます。
:link: readouble.com: コンポーネントとスロット

resources/views/components/btn-del.blade.php
<form style="display:inline" action="{{ url($table.'/'.$id) }}" method="post">
    @csrf
    @method('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の根幹はできあがりました。

144
139
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
144
139