以前に「ティンカーでリクエスト(Request)」で、ティンカーにおいてRequestのオブジェクトをシミュレートできることを紹介しました。あれから数年、ヘルパー関数のrequest()にもティンカーで値を追加できる技を取得しました。

request()に値がない

まず、以前のティンカーでのRequestオブジェクトの作成をここで再現します。

Psy Shell v0.10.8 (PHP 7.4.21 — cli) by Justin Hileman
>>>  $request = \Illuminate\Http\Request::create('http://localhost', 'GET', ['name' => 'test']);
=> Illuminate\Http\Request {#5238
     +attributes: Symfony\Component\HttpFoundation\ParameterBag {#5234},
     +request: Symfony\Component\HttpFoundation\InputBag {#5236},
     +query: Symfony\Component\HttpFoundation\InputBag {#5235},
     +server: Symfony\Component\HttpFoundation\ServerBag {#5231},
     +files: Symfony\Component\HttpFoundation\FileBag {#5232},
     +cookies: Symfony\Component\HttpFoundation\InputBag {#5233},
     +headers: Symfony\Component\HttpFoundation\HeaderBag {#5230},
   }
>>>  $request->all()
=> [
     "name" => "test",
   ]
>>> $request->name
=> "test"
>>>

そして、このRequestオブジェクトを利用して簡単にバリデーションのテストもできます。

>>> $request->validate(['name' => 'required|alpha'])
=> [
     "name" => "test",
   ]
>>> $request->validate(['name' => 'required|numeric'])
Illuminate\Validation\ValidationException with message 'The given data was invalid.'
>>>

しかし、このオブジェクトでは、ヘルバーを使うと期待した値が返ってきません。

>>> request('name')
=> null // "test"と返ってきて欲しい!

どうしてでしょう?

グローバルのRequestオブジェクト

request()の定義を見ると、

...
    /**
     * Get an instance of the current request or an input item from the request.
     *
     * @param  array|string|null  $key
     * @param  mixed  $default
     * @return \Illuminate\Http\Request|string|array
     */
    function request($key = null, $default = null)
    {
        if (is_null($key)) {
            return app('request');
        }

        if (is_array($key)) {
            return app('request')->only($key);
        }

        $value = app('request')->__get($key);

        return is_null($value) ? value($default) : $value;
    }
...

app('request')というのがヘルパーで使用しているRequestのオブジェクトのようです。
ティンカーでタイプしてみると、

>>> app('request');
=> Illuminate\Http\Request {#77
     +attributes: Symfony\Component\HttpFoundation\ParameterBag {#68},
     +request: Symfony\Component\HttpFoundation\InputBag {#70},
     +query: Symfony\Component\HttpFoundation\InputBag {#65},
     +server: Symfony\Component\HttpFoundation\ServerBag {#69},
     +files: Symfony\Component\HttpFoundation\FileBag {#74},
     +cookies: Symfony\Component\HttpFoundation\InputBag {#73},
     +headers: Symfony\Component\HttpFoundation\HeaderBag {#76},
   }

先に作成したRequestのオブジェクトのIDは、#5238なのにこちらは#77で、Laravelのプログラムの実行(ティンカーの実行)のかなり初期に作成されたオブジェクトということがわかります。そして、そのオブジェクトはLaravelがサービスコンテナーとして管理するグローバルにアクセス可能なRequestのオブジェクトです。

そして、以下のようにこのオブジェクトに値を追加することも可能なのです。

>>> app('request')->all();
=> []
>>> app('request')->merge(['name' => 'test']);
=> Illuminate\Http\Request {#77
     +attributes: Symfony\Component\HttpFoundation\ParameterBag {#68},
     +request: Symfony\Component\HttpFoundation\InputBag {#70},
     +query: Symfony\Component\HttpFoundation\InputBag {#65},
     +server: Symfony\Component\HttpFoundation\ServerBag {#69},
     +files: Symfony\Component\HttpFoundation\FileBag {#74},
     +cookies: Symfony\Component\HttpFoundation\InputBag {#73},
     +headers: Symfony\Component\HttpFoundation\HeaderBag {#76},
   }
>>> app('request')->all();
=> [
     "name" => "test",
   ]
>>> app('request')->name
=> "test"

そして、ヘルパーでも値を取得できるようになります。

>>> request('name')
=> "test"

By khino