10. Request
Requestクラス
Requestクラスの基本
「Request」はHTTPリクエスト処理をシンプルに操作できるクラスです。Laravelのサービスコンテナで事前処理しており、PHP標準のグローバル変数を使わず、プログラムの1つの理想型とされるDI(依存注入)なコーディングが簡単にできます。
DI(依存注入)とは
Dependency Injection(DI)は、依存部分を外部から注入すること手法をいいます。依存性のあるプログラムはメンテナンスやテストが難しくなるため、DIで解決する必要があります。
Requestクラスの利用
Requestクラスは「Illuminate\Http\Request」を use します。
use Illuminate\Http\Request;
Requestインスタンス
LaravelのControllerメソッドの引数にRequestインスタンスを指定すると、Requestインスタンスが利用できる状態になっています。
public function score(Request $request)
{
}
引数の順番
Requestインスタンスの引数の順番を変えても動作します。
public function update(int $id, Request $request)
{
}
Requestのメソッド
Requestのメソッドで代表的なものをピックアップします。
all()
all() はリクエストデータをすべて取得します。
$request->all();
input()
input() はパラメータを指定して、リクエストデータを取得します。
$request->input(パラメータ);
toArray()
toArray() は all() のデータを配列で取得するメソッドです。
$request->toArray();
url()
url() は現在のURL(GETパラメータなし)を取得します。
$request->url();
path()
path() は、ホスト部分を除いたURLパスを取得します。
$request->path();
商品入力画面
商品データ入力画面を作成し、リクエストデータを取得してみましょう。
ファイル構成
├── Controllers
│ └── ItemController.php
├── views/
│ ├── item/
│ │ ├── create.blade.php
│ │ ├── edit.blade.php
│ │ ├── index.blade.php
│ │ └── show.blade.php
├── Models/
│ └── Item.php
ルーティング
「item/create」のルーティングを追加します。注意点として 「item/{id}」とパラメータが重複しないように、先に記述しておきます。
web.php
...
Route::get('/item/create', [ItemController::class, 'create'])->name('item.create');
Route::get('/item/{id}', [ItemController::class, 'show'])->name('item.show');
Route::get('/item/edit/{id}', [ItemController::class, 'edit'])->name('item.edit');
入力画面
Viewファイル作成
新規商品の入力画面「item/create.blade.php」を作成します。
@extends('layouts.app')
@section('content')
<h2 class="mt-2">新規商品追加</h2>
<div>
</div>
@endsection
入力フォーム
入力フォームを追加します。HTTPメソッドは「POST」とします。
item/create.blade.php
<form action="" method="post">
<div class="form-group mb-3">
<label class="form-label" for="">商品名</label>
<input type="text" name="name" class="form-control">
</div>
<div class="form-group mb-3">
<label class="form-label" for="">価格</label>
<input type="number" name="price" class="form-control">
</div>
<button class="btn btn-primary">追加</button>
</form>
View表示
ItemController->create() で、「item/create.blade.php」を表示します。
ItemController.php
public function create()
{
return view('item.create');
}
動作確認
「item/create」にアクセスして、入力画面が表示されるか確認してみましょう。
データ送信
CSRF
CSRF とは
CSRF(Cross Site Request Foreign) は、Webシステムを悪⽤してリクエストを偽装するサイバー攻撃の1つです。例えばSNSにログイン中に、悪意のあるURLにアクセスしてユーザーが意図しないメッセージを投稿できます。CSRF 対策として、サーバでワンタイムトークンを発⾏し、正しいページから送信されたか判別します。
LaravelのCSRF
Laravelでフォームは、CSRF対策のためデフォルトで送信できないようになっています。入力画面でフォーム送信すると「Page Expired」エラーページが表示されます。
LaravelではBladeに「@csrf」を記述すると、CSRF用のフォームタグが自動挿入されます。
@csrf
ルーティング
「item/store」のルーティングをPOSTリクエストで追加します。
web.php
Route::post('/item/store', [ItemController::class, 'store'])->name('item.store');
Viewの修正
URL設定
「item/create.blade.php」のactionに、URLパス「item/store」を設定します。
item/create.blade.php
<form action="{{ route('item.store') }}" method="post">
...
</form>
CSRF設定
formタグの中に、CSRFを追加します。
item/create.blade.php
<form action="{{ route('item.store') }}" method="post">
@csrf
...
</form>
データ取得
store() でリクエストを取得し、dd() でデータをデバッグ表示します。
ItemController.php
public function store(Request $request)
{
$posts = $request->all();
dd($request);
}
動作確認
データを入力して送信します。
デバッグ表示して送信データを確認してみましょう。「_token」はCSRFトークンです。
リダイレクト
Laravelのリダイレクトは「Illuminate\Http\RedirectResponse」を利用します。
リダイレクトのメソッド
redirect()
redirect() にパスを指定してリダイレクトします。通常はこのメソッドを利用します。第2引数にURLパラメータも指定できます。
return redirect(パス, パラメータ);
- Controllerのメソッド内で return が必要
route()
redirect() でインスタンスを取得し、route() にルート名を指定してリダイレクトします。第2引数にURLパラメータも指定できます。
return redirect()->route(ルート名, パラメータ);
action()
redirect() でインスタンスを取得し、action() にControllerクラスとメソッド名を指定してリダイレクトします。
return redirect()->action([Controllerクラス, メソッド名], パラメータ);
back()
back() で直前のURLにリダイレクトします。
return back();
withInput()
withInput() はリクエストデータをセッションに一時保存します。redirect() や back() と併用して利用します。
return back()->withInput();
リダイレクト処理
データ更新後に、商品のトップページにリダイレクトしてみます。
View作成
商品トップページのView「item/index.blade.php」を作成します。入力フォームページ「item/create」のリンクも追加します。
item/index.blade.php
@extends('layouts.app')
@section('content')
<h2 class="mt-2">商品</h2>
<div>
<a href="route('item.create')" class="btn btn-outline-primary">新規追加</a>
</div>
@endsection
ルーティング
ルート名「item.index」でルーティング「item/」を追加します。
web.php
Route::get('/item/', [ItemController::class, 'index'])->name('item.index');
リダイレクト
ItemController->store() で「item/」にリダイレクトします。デバッグ処理は削除しておきましょう。
ItemController.php
public function store(Request $request)
{
$posts = $request->all();
return redirect()->route('item.index');
}
動作確認
更新ボタンをクリックして、商品トップページにリダイレクトするか確認してみましょう。