Laravelでフォームのデータを処理する（１／２）フォームで送信されたデータを取得しDBに挿入する

#はじめに
掲示板のようなWebサービスを作成しております。

今回やりたいこと：
Laravelで、
（１）フォームで送信されたデータを取得し、DBにデータとして挿入する。
（２）DBのデータをトップページに並べて表示する。
こんな初歩的な機能ですが、頭を抱えまくったのでメモしておきます。Laravelでこれを実現するには、色々な方法があるみたいですが、初心者の時速40kmの走行方法（教習所内）をメモしておきたいと思います。今回は（１）を（2は次回記事で）。

環境：
Laravel 7.26.1、MAMP 5.7
MAMP以外をご利用の方はそこだけ貴方の環境に合わせて変換していただければと思います。

#１、phpMyAdminでDBのテーブルを用意する
後述しますが、データがなくて空白でも構わないカラムはNULLの設定をしておきます。これをしておかないとエラーの原因になり得ます。
LaravelとphpMyAdminが接続できる状態になっていることが必要です。そのやり方がわからない方はこちらをどうぞ→[LaravelからMAMPを使ってDBに接続するのに四苦八苦した話](https://qiita.com/kakudaisuke/items/53d63acc3aa38c2c5bc1)

#２、フォームのページを作りブラウザに表示する
###フォームを表示するページを準備する
今回はBladeテンプレートで作成しました。スタイルのコードは割愛します。

```html:post.blade.php
<body>
  <div class="form_container">
    <form action="insert" id="create-account" method="POST">
      @csrf
        <h1>{{$user}}さん、ライブの感想を記録しましょう</h1>
        <label for="live_date">ライブに行った日</label>
        <input type="date" id="live_date" name="live_date">
        <label for="musician">ミュージシャン</label>
        <input type="text" id="musician" name="musician">
        <label for="venue">ライブ会場</label>
        <input type="text" id="venue" name="venue">
        <label for="text">ライブの感想</label>
        <textarea name="text" id="text" cols="30" rows="10"></textarea>
        <p style="text-align: right; font-size: 0.8rem;">（1000文字以内）</p>
        <input type="submit" class="submit">
      </form>
  </div><!-- /.form_container -->
</body>
```
ポイント↑

* formのaction属性：これが送信ボタンを押した時のアドレスになる（この場合/insert）
* inputのname属性：これをキーにしてデータを取得する

###コントローラの準備
マネージャなのか、マネージャーなのか。コントローラーなのかコントローラなのか外来語ってめんどくさいなと書いてて思いつつ、Controllerを作成します。Controllerはここでは、今作ったView（post.blade.php）を呼び出したり、変数を渡す役割を担います。

まずはコントローラをターミナルで作成します↓。ファイル名は今回はPostControllerとしましたが、○○○Controllerとして頭とCは大文字とするのが一般的なようです。

```terminal
$ php artisan make:controller ファイル名
```
成功すると`/app/Http/Controllers`の下にファイルができています。（こういうのが魔法みたいで地味にゾクッとします！）
このPostControllerで先のpost.blade.phpを呼び出すために、VS Codeなどのテキストエディタで開いて、下記のように編集します。

```php:PostController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\DB; //←追加。DB接続に必要なクラスをインポートする。

class PostController extends Controller
{
    //アクションメソッドの追加
    public function post(Request $request) {
        $data = [
            'user'=>'ゲスト',
        ];
        return view('post', $data); //viewsフォルダのpostファイルに$dataを渡しつつページ表示する
    }
```
viewメソッドでは`((views下のフォルダー名.ファイル名), 渡す変数)`とパラメータを取りますが、今回post.blade.phpはviewsフォルダの直下に置いてますので、省略しました。
post.blade.phpに渡す変数がなければ`$data`の箇所はなくてもOKですが、今回`{{$user}}`というのを埋め込んでいるので渡してあげます。
###ルーティングの設定
次にユーザーがどのアドレスURLにアクセスしたらこのコントローラを呼び出すかというルーティング設定します。routesフォルダ直下のweb.phpを開きます。

```php:web.php
Route::get('post', 'PostController@post');
```
/postアドレスが選択されると、PostController内のpostメソッドが実行されるようになります。
###表示してみる
http://localhost:8888/jazz-review/public/post にアクセスすると、index.blade.phpに記述したフォームがブラウザに表示されます。
#３、送信した内容を取得し、DBに挿入する
###データを取得する
Controllerにアクションメソッドcreateを追加します。

```php:PostController.php
class PostController extends Controller
{
    public function index(Request $request)
    {
        $items = DB::select('select * from reviews');
        return view('index', ['items' => $items]);
    }

    //こちらを追加。formの値を取得し$paramに代入
    public function create(Request $request) {
        $param = [
            'live_date' => $request->live_date, //取得したいデータをinput要素のname属性
            'musician' => $request->musician,
            'venue' => $request->venue,
            'text' => $request->text,
        ];
        //DBに接続しデータを挿入する。第１パラメータにSQL文、第２に$paramを。
        DB::insert('insert into reviews (live_date, musician, venue, text, created_at) values (:live_date, :musician, :venue, :text, NOW())', $param);
        //トップページに遷移する
        return redirect('/');
    }
}
```
投稿日時を、例えば`created_at(DATETIME)`というカラムに挿入したいする場合は、上記のように、created_atとNOW()を入れると取得できました。
###ルーティングの設定

```php:web.php
Route::get('post', 'PostController@post');
Route::post('insert', 'PostController@create'); //←追加
```
/insertというアドレス（URL）が指定されたら、PostControllerのcreateメソッドを実行せよというルーティング設定です。このアドレスはどこで設定しているかというと、input.blade.phpのformタグのaction属性です。

（余談）当初、formタグのaction属性を理解しておらず、一個上のルートと同様'post'にしていてフォームの送信ボタンを押すと`404 NOT FOUND`になるというエラーに苦しんでいました。よくURLを見ると、設定した覚えがない/insertというアドレスに遷移していたのですが、自分でformタグ内で設定していたのでした。。。

#４、成功
この状態でフォームに必要事項を記入し、送信ボタンを押すと、phpMyAdminにそのデータが挿入され、トップページに遷移します。
悩めば悩んだ分だけ、うまくいった時の喜びが大きくて、こんなしょぼい機能の実装だけで興奮できるので初心者って幸せです。


#５、エラーが起きる場合は？
この記事通りにやってもうまくいきませんか？その場合は、下記を試してみてください。

* エラーメッセージの理解に努める
* スペルミス、セミコロンなどの忘れがないか
* DBに必要なカラム全て（NULL設定ではないカラム＝NULLが許されていないカラム）にデータを挿入できているか。
* 私にコメントを送ってください。


#最後に
以上が、「（１）フォームで送信されたデータを取得し、DBにデータとして挿入する。」でした。次の記事で「（２）DBのデータをトップページに並べて表示する。」を整理したいと思います。
もしご指摘ありましたら、どうぞよろしくお願い申し上げます。