下記イラストのような画面遷移をもつCRUD(Create/Read/Update/Delete)アプリケーションを作成します。
booksテーブルを作成し、titleとauthorを新規登録/編集し、また削除する機能を作成します。本記事ではMySQLを利用し、あらかじめsample01データベースを用意しておきます。.envに適当な値を設定します。
.env
1 2 3 4 5 6 |
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=sample01 DB_USERNAME=hoge DB_PASSWORD=pass |
データベース接続に関しては下記のページもご覧下さい。
モデル、コントローラー、ビューの順番に作成し、最後にバリデーションの機能を追加します。
モデルの作成
まずモデルとマイグレーションファイルを作成します。
1 |
$ php artisan make:model Book --migration |
モデルとマイグレーション自体の詳しい説明についてはこちら
以上でbooksテーブルに対応したモデル(app/Book.php)とマイグレーションファイルが生成されるので、それぞれ下記のように追記します(ハイライト部分)。
app/Book.php
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { protected $fillable = [ 'title', 'author', ]; } |
fillableでデータ登録の際の複数代入のホワイトリストを追記しておきます。これを設定しないと後に作成するコントローラーの下記の箇所でエラーとなります。
1 |
Book::create($request->all()); |
database/migrations/ディレクトリ以下にタイムスタンプ付きのファイルが生成されるので編集します。
2020_01_29_005709_create_books_table.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateBooksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('books', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('title'); $table->string('author'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('books'); } } |
マイグレーションを実行します。
1 |
$ php artisan migrate |
完了するとbooksテーブルが生成されているのが確認できます。
1 2 3 4 5 6 7 8 9 10 |
mysql> SHOW COLUMNS FROM books; +------------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+---------------------+------+-----+---------+----------------+ | id | bigint(20) unsigned | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | author | varchar(255) | NO | | NULL | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | +------------+---------------------+------+-----+---------+----------------+ |
コントローラーの作成
次に–resourceを付けてコントローラーファイルを作成します。
1 |
$ php artisan make:controller BookController --resource |
web.phpに下記コードを追記します。
routes/web.php
1 |
Route::resource('/book', 'BookController'); |
設定されているルート情報を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ php artisan route:list +--------+-----------+------------------+--------------+---------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+-----------+------------------+--------------+---------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | book | book.index | App\Http\Controllers\BookController@index | web | | | POST | book | book.store | App\Http\Controllers\BookController@store | web | | | GET|HEAD | book/create | book.create | App\Http\Controllers\BookController@create | web | | | GET|HEAD | book/{book} | book.show | App\Http\Controllers\BookController@show | web | | | PUT|PATCH | book/{book} | book.update | App\Http\Controllers\BookController@update | web | | | DELETE | book/{book} | book.destroy | App\Http\Controllers\BookController@destroy | web | | | GET|HEAD | book/{book}/edit | book.edit | App\Http\Controllers\BookController@edit | web | +--------+-----------+------------------+--------------+---------------------------------------------+--------------+ |
–resourceを付けることにより作成したコントローラーファイルに各アクションである index() / create() / store() / show() / edit() / update() / destroy() があらかじめ記述されているのが確認できます。それぞれ下記のように追記します(ハイライト部分)。
app/Http/Controllers/BookController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Book; class BookController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { $books = Book::all(); return view('book.index', compact('books')); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { return view('book.create'); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { Book::create($request->all()); return redirect()->route('book.index')->with('success', '新規登録完了しました'); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { $book = Book::find($id); return view('book.show', compact('book')); } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit($id) { $book = Book::find($id); return view('book.edit', compact('book')); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { $update = [ 'title' => $request->title, 'author' => $request->author ]; Book::where('id', $id)->update($update); return back()->with('success', '編集完了しました'); } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { Book::where('id', $id)->delete(); return redirect()->route('book.index')->with('success', '削除完了しました'); } } |
40行目
フラッシュデータとしてセッションへメッセージを格納しています。
フラッシュデータについてはセッションをご覧下さい。
ビューの作成
bookディレクトリを作成し、一覧/新規作成/詳細/編集画面としての各ビュー(テンプレート)を作成します。
一覧画面
resources/views/book/index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<h1>一覧画面</h1> <p><a href="{{ route('book.create') }}">新規追加</a></p> @if ($message = Session::get('success')) <p>{{ $message }}</p> @endif <table border="1"> <tr> <th>title</th> <th>詳細</th> <th>編集</th> <th>削除</th> </tr> @foreach ($books as $book) <tr> <td>{{ $book->title }}</td> <th><a href="{{ route('book.show',$book->id)}}">詳細</a></th> <th><a href="{{ route('book.edit',$book->id)}}">編集</a></th> <th> <form action="{{ route('book.destroy', $book->id)}}" method="POST"> @csrf @method('DELETE') <input type="submit" name="" value="削除"> </form> </th> </tr> @endforeach </table> |
BookController.phpでの各メソッドとルート情報を考慮して記述していきます。例えば18行目においてbook.showを指定しidをGETメソッドで渡すことによって詳細画面へと遷移します。また19行目ではbook.editを指定しidをGETメソッドで渡しています。21〜25行目においては、HTMLがDELETEメソッドをサポートしていないので@method(‘DELETE’)を付ける必要があります。
4〜6行目
セッションへ格納したメッセージを取得し表示させています。
新規作成画面
resources/views/book/create.blade.php
1 2 3 4 5 6 7 8 9 |
<h1>新規作成画面</h1> <p><a href="{{ route('book.index')}}">一覧画面</a></p> <form action="{{ route('book.store')}}" method="POST"> @csrf <p>タイトル:<input type="text" name="title" value="{{old('title')}}"></p> <p>著者:<input type="text" name="author" value="{{old('author')}}"></p> <input type="submit" value="登録する"> </form> |
詳細画面
resources/views/book/show.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<h1>詳細画面</h1> <p><a href="{{ route('book.index')}}">一覧画面</a></p> <table border="1"> <tr> <th>id</th> <th>title</th> <th>author</th> <th>created_at</th> <th>updated_at</th> </tr> <tr> <td>{{ $book->id }}</td> <td>{{ $book->title }}</td> <td>{{ $book->author }}</td> <td>{{ $book->created_at }}</td> <td>{{ $book->updated_at }}</td> </tr> </table> |
編集画面
resources/views/book/edit.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<h1>編集画面</h1> <p><a href="{{ route('book.index')}}">一覧画面</a></p> @if ($message = Session::get('success')) <p>{{ $message }}</p> @endif <form action="{{ route('book.update',$book->id)}}" method="POST"> @csrf @method('PUT') <p>タイトル:<input type="text" name="title" value="{{ $book->title }}"></p> <p>著者:<input type="text" name="author" value="{{ $book->author }}"></p> <input type="submit" value="編集する"> </form> |
book.updateに対してPUTメソッドでidを渡す必要がありますが、HTMLがPUTメソッドをサポートしていないので削除の時と同じように、今度は@method(‘PUT’)を記述しています。
以上でCRUD機能を持つ基本的なアプリケーションが作成できました。
バリデーション
最後にフォームリクエストによるバリデーション機能を、フォーム画面を持つ新規作成と編集画面に対して追加しておきます。上述してきた内容にバリデーション機能を実装します。
バリデーション自体の詳しい説明については下記ページをご覧下さい。
フォームリクエストクラスを作成し、生成されたファイルに下記のように追記/編集します(ハイライト部分)。
1 |
$ php artisan make:request StoreBook |
app/Http/Requests/StoreBook.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class StoreBook extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'title' => 'required', 'author' => 'required', ]; } public function messages() { return [ 'title.required' => 'タイトルを入力して下さい。', 'author.required' => '著者を入力して下さい。', ]; } } |
BookController.phpコントローラーを下記のように追記/編集します。
作成したフォームリクエストクラスを読み取ります。
1 |
use App\Http\Requests\StoreBook; |
バリデーションが必要なstore()とupdate()の引数のRequestをStoreBookに変更します。
1 |
public function store(StoreBook $request) |
1 |
public function update(StoreBook $request, $id) |
ビュー(テンプレート)側にエラーメッセージ表示部分を追記します。
新規作成画面
resources/views/book/create.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<h1>新規作成画面</h1> <p><a href="{{ route('book.index')}}">一覧画面</a></p> @if ($errors->any()) <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> @endif <form action="{{ route('book.store')}}" method="POST"> @csrf <p>タイトル:<input type="text" name="title" value="{{old('title')}}"></p> <p>著者:<input type="text" name="author" value="{{old('author')}}"></p> <input type="submit" value="登録する"> </form> |
編集画面
resources/views/book/edit.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<h1>編集画面</h1> <p><a href="{{ route('book.index')}}">一覧画面</a></p> @if ($message = Session::get('success')) <p>{{ $message }}</p> @endif @if ($errors->any()) <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> @endif <form action="{{ route('book.update',$book->id)}}" method="POST"> @csrf @method('PUT') <p>タイトル:<input type="text" name="title" value="{{ $book->title }}"></p> <p>著者:<input type="text" name="author" value="{{ $book->author }}"></p> <input type="submit" value="編集する"> </form> |
以上でバリデーションの機能が追加されました。
関連ページ