Laravel日記続き

# 内容
フォーム入力→確認→データベースに操作をするwebページ。
参考にしたサイト
↓
[入力 → 確認 → 送信画面のテンプレ（お問い合わせフォーム）](https://laraweb.net/knowledge/4979/)

[前回](https://qiita.com/okochi/items/c0e4c41770a8f4e4997f)の続きを書く。




# ルーティング

```php:web.php
Route::get('/', function () {
    return view('welcome');
});

Route::get('/test', 'TestController@input');
Route::patch('/test', 'TestController@confirm');
Route::post('/test', 'TestController@execute');

```

参考先そのままに、送信方法(get、patch、post)で処理を分けている。




# 入力画面
### コントローラー
getでアクセスしたコントローラーのinput関数から。

```php:TestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Test;
use Illuminate\Support\ViewErrorBag;
use Illuminate\Support\MessageBag;

class TestController extends Controller
{
    // 入力
    public function input() {
        // レコードを昇順で受け取る
        $tests = Test::orderBy('id', 'asc')->get();
        // 受け取ったレコードをtestForm1(入力画面)に渡す
        return view('testForm1', compact('tests'));
    }
}
```

今回作成したのは入力フォームでレコード一覧を表示しているので早速データベースを使う。
`Test::`を使うため上に`use App\Test`を書いておく。

`compact('tests')` これで$testsの値を'tests'という名前で渡すことができる。他にも渡す方法はいくつかある。
最初はwith()を使って渡してた。

```php:
return view('testForm1')->with('tests', $tests);
```
これでも同じように渡せる。

### ビュー
入力画面。
機能が最小限ではないため長くなってる。完璧でもない中途半端。

```html:testForm1.blade.php

<!-- エラーメッセージ表示部分 -->
<style>
    .errors{
        color: red;
    }
</style>

<div class="errors">
@if($errors->any())
    @foreach ($errors->all() as $error)
        {{ $error }}
    @endforeach
@endif
</div>

<!-- 入力部分 -->
<div>
<form method="post">
    {{ method_field('patch') }}
    {{ csrf_field() }}
    ID:<input type="text" name="id" value="{{ old('id') }}"><br>
    名前:<input type="text" name="name" value="{{ old('name') }}"><br>
    <input type="submit" name="insert" value="登録">
    <input type="submit" name="delete" value="削除">
</form>
</div>

<!-- データベース表示部分 -->
<div>
<table border="1">
    <tr>
        <th>ID</th>
        <th>名前</th>
        <th>登録日</th>
        <th>最終更新日時</th>
    </tr>
@foreach ($tests as $test)
    <tr>
        <td>{{ $test->id }}</a></td>
        <td>{{ $test->name }}</td>
        <td>{{ $test->created_at }}</td>
        <td>{{ $test->updated_at }}</td>
    </tr>
@endforeach
</table>
</div>
```

エラーメッセージは説明省略。
`{{ method_field('patch') }}`は送信方法の指定。(怪しい理解)
`{{ csrf_field() }}`は書かないとエラー出た。(超怪しい理解)CSRF対策らしい。
`{{ old('id') }}`はフォームに入力した値が残るように。ブラウザバックで戻った時やバリデーションで弾かれた時に。(怪)

@をつけてfor文やif文を書ける。phpタグをつけなくてもいいから楽に使えるってことなのかな？
phpの経験があまりないので「これは便利！」という感覚があまりない。(要確認)

送られてきた値は`{{ $名前 }}`で受け取れる。{{}}で囲めばphp?echo?
testsと名前をつけられ送られてきた\$testsは、
id, name, created_at, update_at(DBのカラムたち)を持つレコード(連想配列?)
、を複数持つ二重配列。おそらく。

なので一番目のレコードのnameカラムの値を取得したい場合は、
`{{ $tests[0]->name }}`や`{{ $tests[0]['name'] }}`で受け取れる。


patchで送信しているのでボタンを押したらTestControllerのconfirm関数に行く。(web.phpより)


# 確認画面
### コントローラー
input関数の下にconfirm関数を用意します。DBの追加更新削除機能があるので長い。

```php:TestController.php
// 確認
public function confirm(Request $request){
    // 妥当性確認   Validatorファサードを使うやり方もある
    $request->validate([
        'id' => 'required|integer',
    ]);

    // 押されたボタンで分岐
    // 登録
    if ($request->insert) {
        // 妥当性確認
        $request->validate([
            'name' => 'required|string',
        ]);
        $type = '登録';
        $recode = Test::where('id', $request->id)->first();
    // 更新 既に登録されているIDを入力した場合は更新する
        if ($recode != null) {
            $type = '更新';
        }
    // 削除
    } elseif ($request->delete) {
        $type = '削除';
        $recode = Test::where('id', $request->id)->first();
        if ($recode == null) {
            // エラーメッセージを用意、理解はしてない
            $errors = new ViewErrorBag();
            $message = new MessageBag();
            $message->add('', '存在しないID');
            $errors->put('default', $message);
            // 入力フォームにもどる、一覧を表示するためレコードも渡す
            $tests = Test::orderBy('id', 'asc')->get();
            return view('testForm1', compact('tests', 'errors'));
        }

        $request->name = $recode->name;
    }

    // 値を渡しながらtestForm2(確認画面)へ
    return view('testForm2', compact('request', 'type', 'recode'));
}
```

フォームから送信された値は引数の$requestに入ってます。

妥当性確認の部分ではフォームに入力された値をチェックしている。
ひとつめの`'id' => 'required|integer'`では`id`は必須かつ整数で指定している。
この場合の'id'はtestForm1のinputタグのnameで指定した名前。

バリデーションに弾かれるとその場で自動的に、エラーメッセージを持って元ページにリダイレクトします。それより下の処理は行われない。

分岐部分では[登録][削除]のどちらが押されたかで分岐します。
登録の処理では今度は名前フォームで入力された値をチェックしている。一つにまとめることもできるのですが削除の処理では名前フォームの値を必要としないので分けてしまった。

削除内のエラーメッセージはバリデーションで戻されるエラーメッセージと同じ形式にしようと頑張っています。

値を持ってビューへ。


### ビュー
確認画面のビューは入力画面より短め。

```php:testForm2.blade.php
<p>以下のデータを{{ $type }}してもいい?</p>

<form method="post">
    {{ csrf_field() }}

    <!-- 更新処理の時に比較できるよう -->
    @if ($type == "更新")
        変更前<br>
        ID:{{ $recode->id }} <br>
        部門名:{{ $recode->name }} <br>
        <input type="hidden" name="pid" value="{{ $recode->id }}">
        <input type="hidden" name="pname" value="{{ $recode->name }}">
        <br>
        更新後<br>
    @endif

    ID:{{ $request->id }} <input type="hidden" name="id" value="{{ $request->id }}"><br>
    部門名:{{ $request->name }} <input type="hidden" name="name" value="{{ $request->name }}"><br>
    <input type="submit" name="type" value="戻る">
    <input type="submit" name="type" value="{{ $type }}">
</form>
```

受け取った値を表示しながら確認、更新処理の時だけ比較するために変更前も表示している。




# 結果画面
### コントローラー
DB操作をするだけ、失敗した時の処理とかは書いてない。
DB関連のエラーは致命的なので書くべき。

```php:TestController.php
// 完了
public function execute(Request $request){
    if ($request->type == '登録') {
        // 登録
        Test::insert([
            'id' => $request->id,
            'name' => $request->name,
            'created_at' => now(),
            'updated_at' => now()
        ]);
    } elseif ($request->type == '削除') {
        // 削除
        Test::where('id', $request->id)->delete();
        // Test::destroy($request->id);
    } elseif ($request->type == '更新') {
        // 更新
        Test::where('id', $request->id)->update([
            'name' => $request->name,
            'updated_at' => now()
        ]);
    } elseif ($request->type == '戻る') {
        // 戻ってもフォームに値が残ってるように
        $request->session()->flash('_old_input', ['id' => $request->id, 'name' => $request->name]);
        // 入力フォームに戻る
        $tests = Test::orderBy('id', 'asc')->get();
        return view('testForm1', compact('tests'));
    }

    // 値を渡しながらtestForm3(実行しましたよ画面)へ
    return view('testForm3', compact('request'));
}

```


登録更新削除戻るで分岐、処理後ビューへ。

DBの登録更新削除は他にも方法がある。今回は試したので書いておく。

```php:
// 登録
$test = new Test;
$test->id = $request->id;
$test->name = $request->name;
$test->save();

// 更新
$test = Test::where('id', $request->id)->first();
$test->name = $request->name;
$test->save();

// 削除
Test::destroy($request->id);
```

DB操作は[ここ](https://blog.capilano-fw.com/?p=699)を参考にさせていただきました。

### ビュー
testForm2とほぼ同じ。

```php:testForm3.blade.php
<p>以下のデータを{{ $request->type }}しました</p>

@if ($request->type == "更新")
    更新前<br>
    ID:{{ $request->pid }} <br>
    部門名:{{ $request->pname }} <br>
    <br>
    更新後<br>
@endif

ID:{{ $request->id }}<br>
部門名:{{ $request->name }}<br>

<form method="get">
    <input type="submit" value="戻る">
</form>
```

# おわり
フォーム完成でおわり。
途中からなにを書きたいか分からなくなった。
作った物をまるまる見せるのは疲れたので次からは軽いメモっぽくしていきたい。