Laravel - 13. アクション

ここからはコントローラのアクションメソッドについて詳細に学習していきましょう。コントローラのアクションメソッドとはルーティングから呼び出されるメソッドです。アクションメソッドはブラウザからの送信データ(HTTPリクエスト)を処理できます。

ここでは既存の app/Http/Controllers/HelloController.php コントローラに入力フォームを表示する create アクションと、入力フォームからの送信データを処理する store アクションの2つを追加して、HTTPリクエストを処理する方法について学習します。

まずは app/Http/Controllers/HelloController.phpcreate アクションを追加するところから始めましょう。

<?php

namespace App\Http\Controllers;
use App\Message;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class HelloController extends Controller
{
    public function index()
    {
        $title = "Hello Model!";
        $messages = Message::orderBy("id")->get();
        return view("hello/index", compact("title", "messages"));
    }

    public function create()
    {
        return view("hello/create");
    }
}

このプログラムではあらたに create メソッドを追加しています。また create メソッドでは戻り値となる view 関数の引数に "hello/create" と指定しています。これによって、次に作成する resources/views/hello/create.blade.php がビューファイルとなります。

テキストエディタ上であらたに resources/views/hello/create.blade.php ファイルを作成して以下のように実装します。

resources/views/hello/create.blade.php

@extends('layout.app')

@section('content')
<form action="store" method="post">
    @csrf

    <input type="text" name="text">
    <input type="submit" value="send">
</form>
@endsection

create.blade.php ビューではレイアウト layout.app を指定した後、 form タグを使って入力フォームを定義しています。この form タグは送信ボタンをクリックしたときに store というパスに対してPOSTリクエストを送信します。 また form タグの中に @csrf ディレクティブを記述しています。 @csrf ディレクティブはセキュリティに関係するもので、CSRF攻撃を防ぐためのCSRFトークンを生成します。

具体的には @csrf によって 次のようなタグが生成されます。
<input type="hidden" name="_token" value="J1Ngy5CBSDPUnqqZsWbxJtZYwVOhmYEES8LWUG5L">

このCSRFトークン(hiddenパラメータ)はLaravelフレームワークによって透過的にチェックされるようになっています。Laravelフレームワークは、CSRFトークンを持たないHTTPリクエストを受け付けた場合、処理をキャンセルしてエラーページ(HTTPステータス403)にリダイレクトします。

入力フォームの残りの部分ではテキストボックスと送信ボタンの2つを実装しています。

    <input type="text" name="text">
    <input type="submit" value="send">

今回のプログラムではこのテキストボックスに入力されたデータ、次に作成する HelloControllerstore アクションで処理します。

続いて app/Http/Controllers/HelloController.phpstore アクションを追加します。

<?php

namespace App\Http\Controllers;
use App\Message;
use Illuminate\Http\Request;

class HelloController extends Controller
{
    public function index()
    {
        $title = "Hello Model!";
        $messages = Message::orderBy("id")->get();
        return view("hello/index", compact("title", "messages"));
    }

    public function create()
    {
        return view("hello/create");
    }

    public function store(Request $request)
    {
        $text = $request->input("text");
        return "Request parameters: " . $text;
    }
}

追加した store アクションは引数を受け取る点に注意してください。

public function store(Request $request)

store アクションの $request 引数は Request 型としています。アクションメソッドに Request 型の引数を用意することで、Laravelフレームワークによって Request 型のインスタンスが渡されるようになります。

PHPは関数(メソッド)の引数に型を指定できます。このような仕組みは型宣言(タイプヒンティング)などと呼ばれます。

この Request クラスはLaravelに用意されているもので、リクエストにアクセスするための様々なメソッドが用意されています。

        $text = $request->input("text");

ここでは input メソッドを呼び出すことで入力フォームから送信されたデータにアクセスしています。 input メソッドの引数 "text" は、入力フォームの input タグの name 属性( <input type="text" name="text"> ) と関連しています。

Laravelでリクエストを処理する場合は $_GET 変数や $_POST 変数を直接操作しない点に注意してください。

ルーティングの追加

最後に、追加した2つのアクションメソッドをルーティングと関連付けておきましょう。 routes/web.php ファイルを編集します。

<?php

Route::get('/', function () {
    return view('welcome');
});

Route::get("/hello", "HelloController@index");

Route::get("/hello/create", "HelloController@create");
Route::post("/hello/store", "HelloController@store");

ここではあらたに /hello/create というパスに対して HelloControllercreate アクション、 /hello/store というパスに対して HelloControllerstore アクションを関連付けています。

動作確認

コントローラに2つのアクションを追加し、ルーティングを追加したので、PHPのビルトインWebサーバを使ってWebアプリケーションを起動してみましょう。次のようにコマンドを入力します。

$ php artisan serve --host 0.0.0.0
Laravel development server started: http://0.0.0.0:8000

続いてブラウザを起動してWebアプリケーションにアクセスしてみましょう。

http://localhost:8000/hello/create

実行結果から入力フォームが表示されているのがわかります。またブラウザ上でHTMLソースを表示してCSRFトークンについても確認しておきましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Sample</title>
</head>
<body>
    <h1>Hello Laravel!</h1>
    <hr>
    <form action="store" method="post">
        <input type="hidden" name="_token" 
            value="J1Ngy5CBSDPUnqqZsWbxJtZYwVOhmYEES8LWUG5L">
        <input type="text" name="text">
        <input type="submit" value="send">
    </form>
</body>
</html>

折り返して表示しています。

HTMLソースの中にCSRFトークンが生成されているのがわかります。

次にテキストボックスからメッセージを入力してみましょう。

メッセージを入力したら send ボタンをクリックします。

実行結果ら store アクションによってリクエストパラメータを処理できているのがわかります。

まとめ

  • リクエストパラメータを処理するにはアクションメソッドに Request 型の引数を指定する
  • Request 型のインスタンスの input メソッドを通じてリクエストパラメータにアクセスできる
  • フォームからリクエストパラメータを送信するにはデフォルトでCSRFトークンが必要となる