usersテーブルに関するCRUD機能を実装します。
親記事
Laravel 5.7で基本的なCRUDを作る - Qiita
usersのEloquentモデルを生成する
readouble.com: モデル定義
なお、usersテーブルの場合はapp/User.php
が既に存在するので、モデル生成は不要です。
usersのコントローラーを生成する
今回は、典型的なCRUD機能を提供してくれるリソースコントローラを利用させてもらいます。
readouble.com: リソースコントローラ
> php artisan make:controller UserController --resource
app/Http/Controllers/UserController.php
が生成され、CRUDに関するアクションメソッドも自動で定義されています。
あとは中身の処理を書くだけです。
ルーティングを設定する
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コマンドでルートの設定を確認することもできます。
> php artisan route:list
Eloquentモデルをインポートする
コントローラ内で頻繁に使うことになるので、モデルをインポートしておきます。
use Illuminate\Http\Request;
+ use App\User;
class UserController extends Controller
{
次からは、CRUDの機能をひとつひとつ実装していきます。
index
readouble.com: モデルの取得
ユーザーを一覧表示します。
以前の記事で生成したデータが表示されます。
コントローラ
public function index()
{
$users = User::all();
return view('users.index', ['users' => $users]);
}
ビュー
以前の記事で作ったレイアウトを利用します。
@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を利用しています。
また、後で多言語化に対応させるので、あらかじめ__
メソッド内に文章を記述するようにしています。
readouble.com: 翻訳文字列の取得
- Name
+ {{ __('Name') }}
show
readouble.com: 1モデル/集計の取得
1件だけを表示します。
URL例: http://<APP_URL>/users/show/1
コントローラ
/**
* 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
とします。
readouble.com: モデル結合ルート (Route Model Binding)
ビュー
@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
readouble.com: Inserts
1件を新規追加します。
後の章でバリデーション・ルールを設定するまでは、パスワードの2回入力による確認は機能しません。
URL例: http://<APP_URL>/users/create
コントローラ
// 追加用のフォーム画面へ移動
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);
}
ビュー
@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
readouble.com: CSRF保護
readouble.com: 疑似フォームメソッド
edit, update
readouble.com: Updates
1件を更新します。
今のところ、メールアドレスとパスワードは変更できません。
URL例: http://<APP_URL>/users/2/edit
コントローラ
// 更新用フォーム画面へ移動
/**
* 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
と同じです。
@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
readouble.com: モデル削除
1件を削除します。
現時点では、確認も何もなくいきなり削除します。
コントローラ
/**
* Remove the specified resource from storage.
*
* @param \App\User $user
* @return \Illuminate\Http\Response
*/
public function destroy(User $user)
{
$user->delete();
return redirect('users');
}
ビュー
削除ボタンは色々な場所で使うので、コンポーネントとしてまとめておきます。
readouble.com: コンポーネントとスロット
<form style="display:inline" action="{{ url($table.'/'.$id) }}" method="post">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">
{{ __('Delete') }}
</button>
</form>
先ほど作ったshowページの削除ボタンと置き換えます。
- {{-- 削除ボタンは後で正式なものに置き換えます --}}
- <a href="#" class="btn btn-danger">
- {{ __('Delete') }}
- </a>
+ @component('components.btn-del')
+ @slot('table', 'users')
+ @slot('id', $user->id)
+ @endcomponent
完了
ログインもバリデーションもありませんが、とりあえずCRUDの根幹はできあがりました。