【実務で使えるLaravel】編集画面の表示・更新処理

暇なときに予定を探せるアプリ[yoteiPicker](https://yoteipicker.com/)をリリースしました。

実務で使えるLaravelとして編集画面の作成と更新処理のやり方について解説します。

https://www.kamome-susume.com/enginner-job-change-site/

開発環境
Docker 20.10.7
PHP 7.4.22
Laravel 8.53.1
mySQL 5.7
データベースのツール　phpmyadmin

以下の記事の続きになります。
[【Laravel実務に使える】マイグレーションの作成から一覧画面表示まで](https://qiita.com/kamome_susume/items/4013dfcc9c0b93db7ce1)
[【Laravel8】レイアウト共通化 layoutsファイルのapp.blade.phpのコード例](https://qiita.com/kamome_susume/items/4cb10cf50a090e0d01f0)
[【Laravel】画面遷移させる方法　例：一覧画面から登録画面に遷移](https://qiita.com/kamome_susume/items/8a31ed741e2267bd9f56)
[【実務で使えるLaravel】登録画面フォームの作成と新規登録処理を解説](https://qiita.com/kamome_susume/items/4c5942de620a929a21f4)
[【実務で使えるLaravel】詳細画面の表示　例：一覧画面から詳細画面に遷移](https://qiita.com/kamome_susume/items/10f6774329ac289b7fbe)

##本記事の流れ

①ルーティングの設定
②コントローラーの編集
③編集画面の作成

##実際にコードを書いていこう
今回は、本の管理をするアプリを想定しています。
※これまでの一覧画面や登録画面などは上記の記事一覧をご参照ください。

テーブル設計は以下です。
users,books,categoriesテーブルがあります。

booksテーブル
![スクリーンショット 2021-08-14 18.43.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/306a8a3a-dd0e-be2c-8b94-c6e7e83e2e63.png)
user_idとcateogiry_idはNULLにしています。

##①ルーティングの設定
編集画面のルーティングを設定します。

```php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BookController;

/*
|--------------------------------------------------------------------------
| 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('/', [BookController::class, 'index'])->name('book.index');
// 本の登録画面の表示
Route::get('/create', [BookController::class, 'create'])->name('book.create');
// 本の登録処理
Route::post('/store', [BookController::class, 'store'])->name('book.store');
// 本の詳細
Route::get('/show/{id}', [BookController::class, 'show'])->name('book.show');
// 本の編集画面
Route::get('/edit/{id}', [BookController::class, 'edit'])->name('book.edit');
```

##②コントローラーの編集
コントローラーを編集します。

app>Http>controllers>BookController.php

```php
<?php

namespace App\Http\Controllers;

use App\Models\Book;
use Illuminate\Http\Request;

class BookController extends Controller
{

    public function __construct()
    {
        $this->book = new Book();
    }

    /**
     * 一覧画面
     */
    public function index()
    {
        $books = $this->book->findAllBooks();

        return view('book.index', compact('books'));
    }

    /**
     * 登録画面
     */
    public function create(Request $request)
    {        
        return view('book.create');
    }

    /**
     * 登録処理
     */
    public function store(Request $request)
    {
        $registerBook = $this->book->InsertBook($request);
        return redirect()->route('book.index');
    }

    /**
     * 詳細画面の表示
     */
    public function show($id)
    {
        $book = Book::find($id);

        return view('book.show', compact('book'));
    }

    /**
     * 編集画面の表示
     */
    public function edit($id)
    {
        $book = Book::find($id);

        return view('book.edit', compact('book'));
    }
}
```

##③編集画面を作成
編集画面を作成します。

resources>views>bookの下にedit.blade.phpを作成します。

resources>views>book>edit.blade.php

```php
<h1>編集画面</h1>
```

これでURLに`http://localhost/edit/2`と入力すれば編集画面に遷移できます。

次に一覧画面に編集ボタンを設置し、編集画面を作り込んでいきましょう。その後に、更新処理をしていきます。

##④一覧画面に編集ボタンを設置する
一覧画面に編集ボタンを設置して、ボタンをクリックしたらそれぞれの編集画面に遷移できるようにしましょう。

一覧画面を以下のように編集して編集ボタンを設置しましょう。

resources>views>book>index.blade.php

```php
@extends('layouts.app')

@section('content')
<h1>本を管理</h1>

<table class="table table-striped">
  <thead>
    <tr>
      <th>ブックナンバー</th>
      <th>ブック名</th>
      <th>作成日</th>
      <th>詳細</th>
      <th>編集</th>
    </tr>
  </thead>
  <tbody>
    @foreach ($books as $book)
    <tr>
      <td>{{ $book->book_id }}</td>
      <td>{{ $book->book_name }}</td>
      <td>{{ $book->created_at }}</td>
      <td><a href="{{ route('book.show', ['id'=>$book->book_id]) }}" class="btn btn-primary">詳細</a></td>
      <td><a href="{{ route('book.edit', ['id'=>$book->book_id]) }}" class="btn btn-info">編集</a></td>←追加
    </tr>
    @endforeach
  </tbody>
</table>

<a href="{{ route('book.create') }}">本の登録へ</a>
@endsection
```
以下のように編集ボタンが追加されます。
![スクリーンショット 2021-08-14 21.28.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/310bd0a3-dfc0-4f95-8d1d-a9237ce0c80e.png)
変種ボタンをクリックすると、それぞれの編集ページに画面が遷移します。

##⑤編集画面を作り込みます。
一覧画面からそれぞれの編集画面に遷移できることが確認できたので、編集画面を作り込みます。

resources>views>book>edit.blade.phpを以下のように編集しましょう。

```php
@extends('layouts.app')

@section('content')
<div class="container small">
  <h1>本を編集</h1>
  <form action="{{ route('book.update', ['id'=>$book->book_id]) }}" method="POST">
  @csrf
    <fieldset>
      <div class="form-group">
        <label for="book_name">{{ __('本の名称') }}<span class="badge badge-danger ml-2">{{ __('必須') }}</span></label>
        <input type="text" class="form-control" name="book_name" id="book_name">
      </div>
      <div class="d-flex justify-content-between pt-3">
        <a href="{{ route('book.index') }}" class="btn btn-outline-secondary" role="button">
            <i class="fa fa-reply mr-1" aria-hidden="true"></i>{{ __('一覧画面へ') }}
        </a>
        <button type="submit" class="btn btn-success">
            {{ __('更新') }}
        </button>
      </div>
    </fieldset>
  </form>
</div>
@endsection
```
以下のように一覧画面から編集ボタンをクリックすると、編集画面に遷移できます。
![スクリーンショット 2021-08-14 21.37.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/a7c414f1-6671-3dfb-f2a1-e3627b726708.png)

#更新処理を書く
次に編集画面から本の名称を更新する処理を書いていきます。

##①ルーティングに更新処理を書く
routes>web.phpに以下を追記してください。

```php
// 本の更新処理
Route::post('/update/{id}', [BookController::class, 'update'])->name('book.update');
```

##②コントローラーに更新処理を書く
app>Http>controllers>BookController.phpに更新処理を書くので、以下を追記。

```php
<?php

namespace App\Http\Controllers;

use App\Models\Book;
use Illuminate\Http\Request;

class BookController extends Controller
{

    public function __construct()
    {
        $this->book = new Book();
    }

    /**
     * 一覧画面
     */
    public function index()
    {
        $books = $this->book->findAllBooks();

        return view('book.index', compact('books'));
    }

    /**
     * 登録画面
     */
    public function create(Request $request)
    {        
        return view('book.create');
    }

    /**
     * 登録処理
     */
    public function store(Request $request)
    {
        $registerBook = $this->book->InsertBook($request);
        return redirect()->route('book.index');
    }

    /**
     * 詳細画面の表示
     */
    public function show($id)
    {
        $book = Book::find($id);

        return view('book.show', compact('book'));
    }

    /**
     * 編集画面の表示
     */
    public function edit($id)
    {
        $book = Book::find($id);

        return view('book.edit', compact('book'));
    }

    /**
     * 更新処理
     */
    public function update(Request $request, $id)
    {
        $book = Book::find($id);
        $updateBook = $this->book->updateBook($request, $book);

        return redirect()->route('book.index');
    }
}
```

コントローラーはできるだけ記述量を減らして、モデル(Book.php)に更新のロジックは書いていきます。
`$book = Book::find($id);`でbook_idに基づくレコード1件を取得しています。
※レコード1件取得とは、例えば渡されたbook_idが2の場合、
![スクリーンショット 2021-08-14 22.22.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693248/d5c4d79c-9ffd-730e-853e-ada80a62506d.png)
book_id=2 book_name=Vue、category_id=2の情報を取得するって意味です。

`$updateBook = $this->book->updateBook($request, $book);`で更新処理をかけています。

あとはモデルに更新処理を書いていきます。

##③モデルに更新ロジックをかく

app>Models>Book.phpに以下を記述

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    use HasFactory;

    // モデルに関連付けるテーブル
    protected $table = 'books';

    // テーブルに関連付ける主キー
    protected $primaryKey = 'book_id';

    // 登録・更新可能なカラムの指定
    protected $fillable = [
        'book_id',
        'user_id',
        'category_id',
        'book_name',
        'created_at',
        'updated_at'
    ];
    
    /**
     * 一覧画面表示用にbooksテーブルから全てのデータを取得
     */
    public function findAllBooks()
    {
        return Book::all();
    }

    /**
     * 登録処理
     */
    public function InsertBook($request)
    {
        // リクエストデータを基に管理マスターユーザーに登録する
        return $this->create([
            'book_name' => $request->book_name,
        ]);
    }

    /**
     * 更新処理
     */
    public function updateBook($request, $book)
    {
        $result = $book->fill([
            'book_name' => $request->book_name
        ])->save();

        return $result;
    }

}
```

fiilとsaveの組み合わせで更新処理ができます。
`$book->fill([])->save()`で先ほど取得したレコード1件を更新するよって意味ですね。

これで編集ボタンから編集画面に遷移し、更新することができます。

もしわからない箇所があれば遠慮なくコメントでお知らせください。
※不備がある場合もお知らせください。

暇なときに予定を探せるアプリ[yoteiPicker](https://yoteipicker.com/)をリリースしました。

https://www.kamome-susume.com/enginner-job-change-site/