Laravelでのページの追加方法やコントローラーからビューへデータを渡す方法についてはLaravelでHelloWorldの記事にて学びました。 今回はクライアントから送られるフォームデータの取得をLaravelで行っていきたいと思います。 今回の内容はhttps://readouble.com/laravel/6.x/ja/requests.htmlのドキュメントから確認できます。

Laravelでのリクエストデータの取得

3年以上前に更新されました。情報が古い可能性があります。
更新日 : 2020年02月04日

Laravelでのページの追加方法やコントローラーからビューへデータを渡す方法についてはLaravelでHelloWorldの記事にて学びました。

今回はクライアントから送られるフォームデータの取得をLaravelで行っていきたいと思います。

今回の内容はhttps://readouble.com/laravel/6.x/ja/requests.htmlのドキュメントから確認できます。

HTMLフォームを表示するページの作成

まずはクライアントに入力してもらうフォームを作成していきましょう。

LaravelでHelloWorldの記事でやったように、単純なHTMLフォームを作成します。GETメソッドでHTMLフォームにアクセスできるように、ルーティングの設定・コントローラー・ビューの作成を行っておきましょう。

本記事では、コントローラーはProfileControllerクラスを作成し、formメソッドを作成しました。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class ProfileController extends Controller {

	/**
	 * フォーム表示
	 */
	public function form() {
		return view('profile.form');
	}
}

また、ルーティング設定は以下のようにしています。

Route::get('/form', 'ProfileController@form');

上のコントローラーでは、ビューファイルの指定をview('profile.form')としています。このようにドット区切りでビューファイルを指定すると、resources/views/profile/form.blade.phpのビューファイルを表示することになります。ドット区切りがフォルダ区切りとなります。これはドット(.)の代わりにスラッシュ(/)でも可能です。

ビューで利用するBladeファイル(本記事ではresources/views/profile/form.blade.php)には下記のようなコードを記載していきます。基本の枠組みは初期ページのHTMLであるwelcome.blade.phpと同一ですが、今回はHTMLフォームを作成しています。

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravelのフォーム表示</title>

    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">

    <!-- Styles -->
    <style>
        html, body {
            background-color: #fff;
            color: #636b6f;
            font-family: 'Nunito', sans-serif;
            font-weight: 200;
            height: 100vh;
            margin: 0;
        }

        .flex-center {
            align-items: center;
            margin: 100px 300px 100px 300px;
            justify-content: center;
        }

        .position-ref {
            position: relative;
        }
    </style>
</head>
<body>
    <div class="flex-center position-ref">
        <h1>Laravelのフォームテスト</h1>
        <form method="POST" action="show">
            @csrf
            <dl>
                <dt>名前</dt>
                <dd><input type="text" name="name"></dd>
            </dl>
            <dl>
                <dt>年齢</dt>
                <dd>
                    <select name="age">
                        <option value="">-----</option>
                        @for ($i = 20; $i <= 50; $i++)
                            <option value="{{ $i }}歳">{{ $i }}歳</option>
                        @endfor
                    </select>
                </dd>
            </dl>
            <dl>
                <dt>性別</dt>
                <dd>
                    <input type="radio" name="gender" value="男性">男性
                    <input type="radio" name="gender" value="女性">女性
                </dd>
            </dl>
            <dl>
                <dt>好きなもの</dt>
                <dd>
                    <input type="checkbox" name="favorites[]" value="テレビ">テレビ
                    <input type="checkbox" name="favorites[]" value="ラジオ">ラジオ
                    <input type="checkbox" name="favorites[]" value="映画">映画
                    <input type="checkbox" name="favorites[]" value="本"></dd>
            </dl>
            <dl>
                <dt>メモ</dt>
                <dd><textarea name="memo"></textarea></dd>
            </dl>
            <input type="submit" value="!送信!">
        </form>
    </div>
</body>
</html>

これでプロフィールを入力するフォームの完成です。

HelloWorldで少しだけ触れたBladeテンプレートの機能を2つ利用しているので解説します。

  • @for ($i = 20; $i <= 50; $i++) 〜 @endfor
    PHPのfor文をBladeテンプレートで利用しています。20歳から50歳までの選択リストは数字が変わるだけなのでfor文で生成しました。@forから@endforの間に挟まれたHTMLが繰り返し記述されます。
  • @csrf
    CSRF対策用のBladeテンプレートの機能です。これを記載するだけでCSRFトークンが自動でHTMLとして付与されます。LaravelではCSRF対策チェックをデフォルトで行うため、除外しない限り、フォームにはCSRF用のトークンを必ず埋め込まなければいけません。CSRFについてはこちら

また、好きなものを選択するチェックボックスは、複数のデータを送信できるように、name属性をfavorite[]のように配列として受け取れるようにします。

これでルーティングに設定したURLでフォームが表示されるかと思います。

リクエストデータの受け取りページを作成

次にリクエストデータの受け取りをしていきます。先程のHTMLフォームのPOSTデータの送信先はshowとなっています。(formタグのaction属性)このページを作成していきましょう。

リクエストのルーティング設定

まずはルーティング設定です。今回のshowページはPOSTデータを受け付けるので、POSTで受け付けられるように設定します。ルーティングの設定を下記の用に追加しましょう。

Route::post('/show', 'ProfileController@show');

Route::postになっています。これでshowのURLはPOSTリクエストされた際に、ProfileControllershowメソッドで処理が継続します。

コントローラーのメソッド作成

ProfileControllershowメソッドを実装していきます。先程のProfileControllerに追記していきます。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class ProfileController extends Controller {

	/**
	 * フォーム表示
	 */
	public function form() {
		return view('profile.form');
	}

	/**
	 * プロフィール表示
	 */
	public function show(Request $request) {
		// メモが入力されているか確認
		if($request->filled('memo')) {
			$memo = $request->input('memo');
		} else {
			$memo = 'なし';
		}
		// ビューで使う配列データの作成
		$profile = array(
			'name' => $request->input('name'),
			'age' => $request->input('age'),
			'gender' => $request->input('gender'),
			'favorites' => $request->input('favorites', array('なし')),
			'memo' => $memo
		);
		return view('profile.show', $profile);
	}
}

まず、POSTのリクエストデータを確認するため、classの上にuse Illuminate\Http\Request;と書き、リクエストデータを扱えるようにします。

次にshowメソッドを確認していきます。

まず引数に注目しましょう。show(Request $request)となっています。

これは$requestを引数として受け付ける際に、Requestという型で受け取るという宣言です。これはタイプヒンティングと言います。このRequestは上記で書いたuse Illuminate\Http\Request;のことを表しています。

PHPのタイプヒンティングについては改めて解説記事を記載します。

これでリクエストデータを受け取る準備が整いました。

あとはドキュメント通りにリクエストデータの受け取りを行い、そのデータをビューへ渡す処理を行っていきます。今回行っている処理はhttps://readouble.com/laravel/6.x/ja/requests.htmlこちらに記載されている機能を使用しています。

一応いくつか簡単に解説します。

  • $request->filled('memo')
    Requestクラスのfilledメソッドの利用です。これは引数に'memo'のように、フォームに存在するname属性値を入れることで、そのフォームの入力値にデータが入っているかどうかをチェックしてくれます。
    先程のフォームにあった<textarea name="memo"></textarea>にデータが存在するかどうかをチェックし、入力値が存在すればtrueとなります。
  • $request->input('age')
    Requestクラスのinputメソッドの利用です。これも引数にフォームのname属性値を指定することで、フォームの入力値を取得できます。第二引数には、POSTデータが存在しなかった場合のデフォルト値が指定できます。($request->input('favorites', array('なし'))この部分のarray('なし')がfavoritesのデータが送られなかった場合のデフォルト値)

また、上記フォームのチェックボックスになっている好きなものを選択する部分では、1つのname属性に対して入力が複数になるため、Controllerでは配列で受け取るために、name属性値としてfavorites[]と記載します。[]これを入れることで、Laravel上で配列としてデータを複数受け取ることができます

最後にビューファイルを作成していきましょう。

ビューファイルの作成

先程のコントローラーで実装されたshowメソッドの返り値では、return view('profile.show', $profile);という形でビューファイルを指定しています。そのため、resources/views/profile/show.blade.phpのビューが表示されることになります。

ビューファイル(本記事ではresources/views/profile/show.blade.php)には以下のように書いていきましょう。

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravelのフォーム表示</title>

    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">

    <!-- Styles -->
    <style>
        html, body {
            background-color: #fff;
            color: #636b6f;
            font-family: 'Nunito', sans-serif;
            font-weight: 200;
            height: 100vh;
            margin: 0;
        }

        .flex-center {
            align-items: center;
            margin: 100px 300px 100px 300px;
            justify-content: center;
        }

        .position-ref {
            position: relative;
        }
    </style>
</head>
<body>
    <div class="flex-center position-ref">
        <h1>Laravelのフォーム受信</h1>
        <dl>
            <dt>名前</dt>
            <dd>{{ $name }}</dd>
        </dl>
        <dl>
            <dt>年齢</dt>
            <dd>{{ $age }}</dd>
        </dl>
        <dl>
            <dt>性別</dt>
            <dd>{{ $gender }}</dd>
        </dl>
        <dl>
            <dt>好きなもの</dt>
            <dd>
                @foreach ($favorites as $fav)
                    @if (!$loop->last)
                        {{ $fav }},
                    @else
                        {{ $fav }}
                    @endif
                @endforeach
            </dd>
        </dl>
        <dl>
            <dt>メモ</dt>
            <dd>{{ $memo }}</dd>
        </dl>
    </div>
</body>
</html>

コントローラーから受け取ったデータを表示しているのが主な処理です。

好きなものを複数表示する部分では、foreachifをbladeから利用しています。$loop->lastとすると、ループの最後だった場合にtrueが返却され、条件分岐に利用できます。詳しくはドキュメントを自分で読みながら理解できるようになりましょう。bladeのドキュメントはこちら

これで受け取ったリクエストデータの表示まで実装できました。

フォームと、送信結果は以下のようになっているはずです。

まとめ

今回はLaravelのドキュメントに記載されている通りにHTMLの表示とフォームデータの受け取りを行っていきました。

PHPの基本が理解できていれば、ドキュメントを読むだけである程度使い方がわかるようになっているはずです。そのためLaravelの機能を利用した細かい説明は除外しています。

フレームワーク自体にたくさんの機能が実装されていて、全てを順番に説明するには項目が多すぎます。必要なフレームワークの機能を自分で検索して扱えることに慣れていきましょう。