[Laravel] Requestクラスのメソッドまとめ

# 今回の題
LaravelのRequest周りを調べてまとめました。
基本、[readouble](https://readouble.com/laravel/6.x/ja/requests.html)に載っているものですが、何個か載っていないものも書いています。
試しながら書きましたが、もし間違いや注意点などありましたらコメントにお願いします

# 検証したバージョン
Laravel 6.8

# Requestクラスを利用するには

## 1. DI

```php
    public function store(Request $request)
    {
        $request->input('hoge');
    }
```

## 2. ヘルパ関数

```php
    public function store()
    {
        request('hoge');
    }
```

## 3. ファサード

```php
    public function store()
    {
       Request::input('hoge');
    }
```

# メソッド一覧

## ■HTTP動詞関係

### method() リクエストのHTTP動詞を返す
受け取ったリクエストがGETリクエストなら`GET`、POSTリクエストなら`POST`を返すといった具合

```php
$request->method();
```
### isMethod() 引数に指定した文字列とHTTP動詞が一致するかを判定する
一致すればtrueが、しなければfalseが返る

```php
$request->isMethod('post');
```

## ■URL関係

### root() ルートディレクトリまでのURLを取得する
リクエストされたurlが
`http://localhost/user` なら
`http://localhost` まで取得

```php
$request->root();
```

### url() リクエストされたurlを取得(クエリーストリングは含まない)
リクエストされたurlが
`http://localhost/user?name=hoge` なら
`http://localhost/user` まで取得

```php
$request->url();
```

### fullUrl() リクエストされたurlを取得(クエリーストリングを含む)
リクエストされたurlが
`http://localhost/user?name=hoge` なら
`http://localhost/user?name=hoge` まで取得

```php
$request->fullUrl();
```

### path()　リクエストされたURLのパスを取得
リクエストされたurlが
`http://localhost/user` なら
`user` だけを取得

```php
$request->path();
```

### fullUrlWithQuery() リクエストされたURLに任意のクエリーストリングを付与
リクエストされたurlが
`http://localhost/user` なら以下のコードで
`http://localhost/user?name=hoge` にすることが出来る。

```php
$request->fullUrlWithQuery(['name' => 'hoge',]);
```

### is() リクエストされたURLのパスが指定したパターンに合致するかを確認する
`http://localhost/〜〜/〜〜`　みたいなURLなら
`http://localhost/`以下が条件に合致するかを見る。
なので以下のコードの場合、

```php
$request->is('admin/*');
```
`http://localhost/admin/user` にはtrueを
`http://localhost/user` にはfalseを返す

## ■入力値関係

### all() toArray() input() 入力値を連想配列として取得する
下記の3つはどれも入力値を連想配列として取得することができます。
またその際、GET、POSTは考慮しません。

```php
$request->all();
// ⬇︎ toArrayは内部でall()を呼んでそのまま返してる
$request->toArray(); 
$request->input();
```
**注意点**
all()はファイルを取得することができますが、input()はファイルを取得することができません。

### 動的プロパティ 入力値を個別に取得する

```php
$request->hoge;
```
**注意点**
動的プロパティは、初めにリクエスト本体の値を参照し、値が存在しない場合は続いてルートパラメータを参照します。

↓ 仕組み

```php
public function __get($key)
{
    return Arr::get($this->all(), $key, function () use ($key) {
        return $this->route($key);
    });
}
```

### input() 値を個別に取得する
クエリーストリング、リクエストボディから値を取得できます。

```php
$request->input('hoge');
// ⬇︎第2引数にデフォルト値を設定できる
$request->input('hoge', 'hogehoge');
```
inputは配列から値を取得することもできます。
その際は、カンマ区切りで連想配列のキー、もしくは配列のインデックス番号を指定します。
例えば、

```html
<input type="text" name="user[name]">
```
のような場合、

```php
$request->input('user.name');
```
で値を取得することができます。

### get() 値を個別に取得する
**追記があります**
<a href="#getの利用に関して">get()の利用に関して</a>

クエリーストリング、リクエストボディから入力値を取得できます。

```php
$request->get('hoge');
// 第2引数にデフォルト値を設定できる
$request->get('hoge', 'hogehoge');
```

#### get()とinput()の違い
**追記があります**
<a href="#getの利用に関して">get()の利用に関して</a>

**get()はinput()とは異なり、配列から値を取得することができない。**
**また、引数を取らない場合、input()は値を連想配列で返しますが、get()は引数が必須です。**

```php
// これは動きません
$request->get('user.name');
// これも動きません
$request->get();
```
多くの場合はinput()が使い勝手が良さそうです。

### query() クエリーストリングから取得する
input()やget()は、クエリーストリング、リクエストボディから入力値を取得できますが、
query()はクエリーストリングからのみ値を取得します。

```php
// クエリーストリングを全て連想配列で取得する
$request->query();
// クエリーストリングから個別に値を取得する
$request->query('hoge'); 
// 第２引数にデフォルト値を設定できる
$request->query('hoge', 'hogehoge');
```

### only()　入力値の一部取得(〜のみ取得）
引数に指定した値だけ取得することができます。

```php
// hoge1　hoge２ のみ取得する
$request->only('hoge1', 'hoge2');
// 配列でも受け取れる
$request->only(['hoge1', 'hoge2']);
```

### except()　入力値の一部取得（〜以外取得)
引数に指定した値を省いて取得することができます。

```php
// hoge3を省いて取得する
$request->except('hoge3');
// 配列でも受け取れる
$request->except(['hoge3']);
```

### boolean() 論理入力値の取得
boolean()は、`1、"1"、true、"true"、"on"、"yes"`のいづれかを引数で受け取るとtrueを返し、それ以外の値に関してはfalseを返します。
例えば、こんな感じのラジオボタンがあり、

```html
<form>
  YES:<input type="radio" name="hoge" value="yes">
  NO:<input type="radio" name="hoge" value="no">
</form>
```
YESのラジオボタンをチェックして送信した場合、以下のコードはtrueを返します。

```php
$request->boolean('hoge');
```

### 入力値の存在チェックの前提
前提として、以下のフォームに値を入力して送信したとします。

```html
<form>
  <input type="text" name="hoge1" value="hoge1">
  <input type="text" name="hoge2">
</form>
```
### has() 指定したキーの有無
指定したキーが存在していたらtrue。
無ければfalse。

```php
// true
$request->has('hoge1');
// false
$request->has('hoge3');
// true 複数チェックするときは配列でOK
$request->has(['hoge1', 'hoge2']);
```

### hasAny() 指定した複数キーのいずれかの有無
指定したキーのいずれかが存在していたらtrue。
無ければfalse。

```php
// true hoge1はあるがhoge3はない
$request->hasAny(['hoge1', 'hoge3']);
// false　hoge3もhoge4もない
$request->hasAny(['hoge3', 'hoge4']);
```

### filled() 指定したキーの有無 && 値が入力されているか
キーが存在しており、かつ値が入力されていたらtrue。
キーが存在しない。もしくは未入力（null）だとfalse。

```php
// true
$request->filled(hoge1);
// false
$request->filled(hoge2);
```
※前提でhoge1にはvalueに値を入れてある。

### missing() 指定したキーが無いか
指定したキーがリクエストに存在しなければtrue。
存在すればfalse。

```php
// true
$request->missing('hoge3');
// false
$request->missing('hoge1');
```

## ■フラッシュデータ関係
Laravelではリクエストの入力値を、次のリクエストまでフラッシュデータとしてセッションに保持しておくことができます。

### flash() 入力値を全てフラッシュデータとして保持

```php
$request->flash();
```

### flashOnly() 指定したものだけフラッシュデータとして保持
保持したい情報だけを選んでセッションに保持できます。

```php
$request->flashOnly(['username', 'email']);
```

### flashExcept() 指定したものを省いてフラッシュデータとして保持
セッションに保持すべきでない情報を明示的に省くことができます。

```php
$request->flashExcept('password');
```

#### フラッシュデータに関する余談
直前のページヘリダイレクトして、old()ヘルパでフラッシュデータを利用するような場合、
$request->flash()よりも、withInput()を使うとシンプルに書ける。

```php
$request->flash();
return back();
// ⬇︎ 同義
return back()->withInput();
// 保持したくない情報を省くときはこう
return back()->withInput(
  $request->except('password')
);
```

## ■ファイル関係

### 前提として。
以下のようなフォームを送信して動きを見ます。

```html
<form enctype="multipart/form-data">
  <input type="file" name="image">
<form>
```

### 動的プロパティ ファイルを取得
リクエストされたファイルの情報を持ったUploadedFileクラスのインスタンスが返ります。

```php
$request->image;
```

### file() ファイルを取得
リクエストされたファイルの情報を持ったUploadedFileクラスのインスタンスが返ります。

```php
$request->file('image');
```

### hasFile() ファイルが存在するかどうか

```php
$request->hasFile('image');
```

### ファイル周りをもう少し (UploadedFileクラスのメソッド)

#### isValid() 正常にアップロードできたか

```php
$request->file('image')->isValid();
```

#### path() アップロードされたファイルが一時保存されているテンポラリファイルまでのパスを取得

```php
$request->file('image')->path();
```

#### extension() アップロードされたファイルの拡張子を取得

```php
$request->file('image')->extension();
```

#### store() ファイルの保存
storage/app以下のimagesディレクトリにハッシュ化されたファイル名で保存されます。
imagesディレクトリが存在しなければ実行時に作成されます。

```php
$request->file('image')->store('images');
```

#### storeAs() ファイルを任意のファイル名で保存したい場合
上のstoreをstoreAsに変え、第2引数に任意のファイル名を渡したような感じです。

```php
$request->file('image')->storeAs('images', 'filename.jpg');
```

## ■その他

### ajax() リクエストがajaxか否か
受け取ったリクエストがajaxならtrueを、違っていたらfalseが返る。

```php
$request->ajax();
```

### pjax() リクエストがpjaxか否か
受け取ったリクエストがpjaxならtrueを、違っていたらfalseが返る。

```php
$request->pjax();
```

### ip() IPアドレスを取得する
リクエスト元のIPアドレスを取得します。

```php
$request->ip();
```

### userAgent() User Agentを取得する
リクエストヘッダーからUser Agentを取得します。

```php
$request->userAgent();
```

### validate() バリデーションを行う
多くはFormRequestを使い、役割、責任を分離した方が良いと思いますが、以下のようにも。

```php
$request->validate([
    'name' => 'required',
]);
```

### merge() リクエストに値を追加する 
merge()に配列を渡すと、リクエストに値が追加されます。
**すでに存在するキーを渡すと上書きされます。**

```php
$array = ['hoge' => 'hogehoge'];
$request->merge($array);
$request->input('hoge'); // hogehoge
```

### replace() リクエストの全ての値を任意の配列で再構成する
リクエストの値がreplace()に渡した配列で再構成されます。
~~多分、使う機会ない……~~

```php
$array = ['hoge' => 'hogehoge'];
$request->replace($array);
$request->input('hoge'); // hogehoge
```

### offsetUnset() キーを指定して削除する
※追記をご覧ください

```php
$request->offsetUnset('hoge');
```

### offsetSet() キーを指定して値を書き換える
※追記をご覧ください

```php
$request->input('hoge'); // hoge
$request->offsetSet('hoge', 'hogehoge');
$request->input('hoge'); //hogehoge
```

### routeIs() ルート名が指定した値と一致するか
以下のような名前付きルートの名前が、

```php
Route::get('/', '〜略〜')->name('home');
```
routeIs()の引数の値と一致すればtrue。
一致しなければfalse。

```php
$request->routeIs('home')
```

## 追記
### offsetSet()、offsetUnset()に関して
@nunulk様から情報をいただきました。
Requestクラスには[ArrayAccessインタフェース](https://www.php.net/manual/ja/class.arrayaccess.php)が適応されているので、オブジェクトから配列のように値を取得することが出来ます。GET、POSTは考慮しません。
因みに存在しないキーを呼ぶとnullが返ります。

```php
$request['hoge'];
```
値の書き換え、追加、削除もできます。

```php
$request['hoge'] = 'hoge_hoge';
// $request->offsetSet('hoge', 'hogehoge'); と同じ

unset($request['hoge']);
// $request->offsetUnset('hoge'); と同じ
```
先に挙げたメソッド、offsetSet()、offsetUnset()は、この時に呼び出されるメソッドでした。

### get()の利用に関して
↓結論↓
**極力input()を使いましょう！！**

get()のソースに以下のようなコメントがありました。
>This method belongs to Symfony HttpFoundation and is not usually needed when using Laravel.
Instead, you may use the "input" method.

LaravelのRequestクラスはSymfony\Component\HttpFoundation\Requestを継承して作らているので、それに由来するコードが幾つかあります。get()もその一つで、コメントを見る限りではLaravelでは通常使う必要は無いそうです。
**極力input()を使いましょう！！**

## 一言
めちゃくちゃ多いですね汗
QiitaはPCなどの画面の広い端末で見れば右側に目次が表示されるので比較的見やすいと思います。
Requestを経由したsessionの使い方に関してはまた別の記事にしようと思います。

## 参考

[Illuminate\Http\Request.php](https://github.com/illuminate/http/blob/6.x/Request.php)
[readouble](https://readouble.com/laravel/6.x/ja/requests.html)