ホームページ  >  記事  >  バックエンド開発  >  リクエストのLaravelコア解釈

リクエストのLaravelコア解釈

不言
不言オリジナル
2018-07-06 14:54:374051ブラウズ

この記事では主に、一定の参考価値のあるLaravel Requestのコア解釈を紹介します。今から皆さんに共有します。必要な友人は参考にしてください。

Request

多くのフレームワークは、クライアントからのリクエストは、アプリケーションで簡単に使用できるようにクラスに抽象化されます。Laravel も例外ではありません。 Illuminate\Http\Request クラスは、Laravel フレームワークのクライアント リクエストの抽象化であり、Symfony フレームワークによって提供される Request コンポーネントに基づいて構築されます。今日の記事では、Laravel が Request オブジェクトを作成する方法について簡単に説明します。Request オブジェクトがアプリケーションに提供する機能については、あまり詳しく説明しません。作成プロセスの説明が終わったら、どこに行くべきかがわかるでしょう。ソース コードです。Request オブジェクトによって提供されるメソッドを探します。インターネット上の一部のチートシートには、Request によって提供されるメソッドがリストされていますが、それらは完全ではなく、説明されていないものもあります。したがって、興味がある場合は、これをお勧めします。 Request が開発中に希望する機能を実現しているかどうかについて Request のソースコードにアクセスして、対応するメソッドがあるかどうかを確認し、各メソッドの実行結果をメソッドのコメントに明示します。本題に入りましょう。

Request オブジェクトの作成

Laravel アプリケーションの index.php ファイルで、Laravel アプリケーションが正式に開始される前に Request オブジェクトが作成されたことがわかります。 OK:

//public/index.php
$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    //创建request对象
    $request = Illuminate\Http\Request::capture()
);

クライアントの HTTP リクエストは、Illuminate\Http\Request を介した

Illuminate\Http\Request

クラス <pre class="brush:php;toolbar:false;">class Request extends SymfonyRequest implements Arrayable, ArrayAccess { //新建Request实例 public static function capture() { static::enableHttpMethodParameterOverride(); return static::createFromBase(SymfonyRequest::createFromGlobals()); } }</pre> のオブジェクトです。ソースコードから、Symfony Request クラスから継承していることがわかります。そのため、Illuminate\Http\Request クラスに実装された多くの関数は、Symfony Reques# によって提供されています。 ## 関数ベースの実装。上記のコードから、capture メソッドは、新しい Request オブジェクトを作成するときに Symfony Request クラスのインスタンスにも依存していることがわかります。

namespace Symfony\Component\HttpFoundation;
class Request
{
    /**
     * 根据PHP提供的超级全局数组来创建Smyfony Request实例
     *
     * @return static
     */
    public static function createFromGlobals()
    {
        // With the php&#39;s bug #66606, the php&#39;s built-in web server
        // stores the Content-Type and Content-Length header values in
        // HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields.
        $server = $_SERVER;
        if (&#39;cli-server&#39; === PHP_SAPI) {
            if (array_key_exists(&#39;HTTP_CONTENT_LENGTH&#39;, $_SERVER)) {
                $server[&#39;CONTENT_LENGTH&#39;] = $_SERVER[&#39;HTTP_CONTENT_LENGTH&#39;];
            }
            if (array_key_exists(&#39;HTTP_CONTENT_TYPE&#39;, $_SERVER)) {
                $server[&#39;CONTENT_TYPE&#39;] = $_SERVER[&#39;HTTP_CONTENT_TYPE&#39;];
            }
        }

        $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server);

        if (0 === strpos($request->headers->get(&#39;CONTENT_TYPE&#39;), &#39;application/x-www-form-urlencoded&#39;)
            && in_array(strtoupper($request->server->get(&#39;REQUEST_METHOD&#39;, &#39;GET&#39;)), array(&#39;PUT&#39;, &#39;DELETE&#39;, &#39;PATCH&#39;))
        ) {
            parse_str($request->getContent(), $data);
            $request->request = new ParameterBag($data);
        }

        return $request;
    }
    
}

上記のコードには追加の説明が必要な点が 1 つあります。PHP5.4 以降、PHP の組み込み Web サーバーは、コマンド ライン インタープリターを介して起動できます。例:

php -S localhost:8000 -t htdocs

-S 9581b3ba3b9ee3c707d01b5722440004:298c9bd6ad6e8c821dc63aa0473d6209 Run with built-in web server.
-t ea23c61ebf6b70b26359136364366495     Specify document root ea23c61ebf6b70b26359136364366495 for built-in web server.
しかし、組み込み Web サーバーには 2 つのリクエスト ヘッダー

CONTENT_LENGTHCONTENT_TYPE を保存するバグがあります。 HTTP_CONTENT_LENGTHHTTP_CONTENT_TYPE では、組み込みサーバーと実サーバーのリクエスト ヘッダー フィールドを統一するために、ここで特別な処理が行われます。

Symfony Request インスタンスは、PHP のスーパー グローバル配列を通じて作成されます。これらのスーパー グローバル配列には、

$_GET$_POST$ _COOKIE$_FILES$_SERVER は、PHP の HTTP リクエストに関連するすべてのスーパー グローバル配列をカバーします。Symfony Request インスタンスを作成するとき、Symfony パッケージはこれらのグローバル配列に基づいて作成されます。 ##ParamterBag ServerBag FileBag HeaderBag インスタンスこれらのバッグは、さまざまな HTTP コンポーネント用に Symfony が提供する API にアクセスおよび設定します。これらに興味のある読者Symfony が提供する ParamterBag の例では、ソース コード自体をチェックアウトできます。ここでは詳細は説明しません。 <pre class="brush:php;toolbar:false;">class Request { /** * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string|resource|null $content The raw body data */ public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this-&gt;initialize($query, $request, $attributes, $cookies, $files, $server, $content); } public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this-&gt;request = new ParameterBag($request); $this-&gt;query = new ParameterBag($query); $this-&gt;attributes = new ParameterBag($attributes); $this-&gt;cookies = new ParameterBag($cookies); $this-&gt;files = new FileBag($files); $this-&gt;server = new ServerBag($server); $this-&gt;headers = new HeaderBag($this-&gt;server-&gt;getHeaders()); $this-&gt;content = $content; $this-&gt;languages = null; $this-&gt;charsets = null; $this-&gt;encodings = null; $this-&gt;acceptableContentTypes = null; $this-&gt;pathInfo = null; $this-&gt;requestUri = null; $this-&gt;baseUrl = null; $this-&gt;basePath = null; $this-&gt;method = null; $this-&gt;format = null; } }</pre>Symfony Request クラスには、上で説明したものに加えて多くの属性があることがわかります。これらの属性は一緒になって HTTP リクエストの完全な抽象化を形成します。インスタンス属性を通じて簡単にアクセスできます

Method

Charset、およびこれらの HTTP リクエストのその他の属性。 Symfony Request インスタンスを取得した後、Laravel はインスタンスのクローンを作成し、そのプロパティの一部をリセットします:

namespace Illuminate\Http;
class Request extends ....
{
    //在Symfony request instance的基础上创建Request实例
    public static function createFromBase(SymfonyRequest $request)
    {
        if ($request instanceof static) {
            return $request;
        }

        $content = $request->content;

        $request = (new static)->duplicate(
            $request->query->all(), $request->request->all(), $request->attributes->all(),
            $request->cookies->all(), $request->files->all(), $request->server->all()
        );

        $request->content = $content;

        $request->request = $request->getInputSource();

        return $request;
    }
    
    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
    {
        return parent::duplicate($query, $request, $attributes, $cookies, $this->filterFiles($files), $server);
    }
}
    //Symfony Request中的 duplicate方法
    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
    {
        $dup = clone $this;
        if (null !== $query) {
            $dup->query = new ParameterBag($query);
        }
        if (null !== $request) {
            $dup->request = new ParameterBag($request);
        }
        if (null !== $attributes) {
            $dup->attributes = new ParameterBag($attributes);
        }
        if (null !== $cookies) {
            $dup->cookies = new ParameterBag($cookies);
        }
        if (null !== $files) {
            $dup->files = new FileBag($files);
        }
        if (null !== $server) {
            $dup->server = new ServerBag($server);
            $dup->headers = new HeaderBag($dup->server->getHeaders());
        }
        $dup->languages = null;
        $dup->charsets = null;
        $dup->encodings = null;
        $dup->acceptableContentTypes = null;
        $dup->pathInfo = null;
        $dup->requestUri = null;
        $dup->baseUrl = null;
        $dup->basePath = null;
        $dup->method = null;
        $dup->format = null;

        if (!$dup->get(&#39;_format&#39;) && $this->get(&#39;_format&#39;)) {
            $dup->attributes->set(&#39;_format&#39;, $this->get(&#39;_format&#39;));
        }

        if (!$dup->getRequestFormat(null)) {
            $dup->setRequestFormat($this->getRequestFormat(null));
        }

        return $dup;
    }

Request オブジェクトが作成されたら、それを Laravel アプリケーションに簡単に適用できます。 Request オブジェクトを使用すると、必要な機能が実現されているかどうかがわからない場合、

Illuminate\Http\Request

のソース コード ファイルに直接アクセスして確認するのが非常に簡単です。このソース コード ファイルでは、次のようにリストされます。 <pre class="brush:php;toolbar:false;">/** * Get the full URL for the request. * 获取请求的URL(包含host, 不包括query string) * * @return string */ public function fullUrl() { $query = $this-&gt;getQueryString(); $question = $this-&gt;getBaseUrl().$this-&gt;getPathInfo() == &amp;#39;/&amp;#39; ? &amp;#39;/?&amp;#39; : &amp;#39;?&amp;#39;; return $query ? $this-&gt;url().$question.$query : $this-&gt;url(); } /** * Get the full URL for the request with the added query string parameters. * 获取包括了query string 的完整URL * * @param array $query * @return string */ public function fullUrlWithQuery(array $query) { $question = $this-&gt;getBaseUrl().$this-&gt;getPathInfo() == &amp;#39;/&amp;#39; ? &amp;#39;/?&amp;#39; : &amp;#39;?&amp;#39;; return count($this-&gt;query()) &gt; 0 ? $this-&gt;url().$question.http_build_query(array_merge($this-&gt;query(), $query)) : $this-&gt;fullUrl().$question.http_build_query($query); }</pre>リクエストが通過するステーション

リクエスト オブジェクトを作成した後、Laravel の Http カーネルは実行を継続します。サービス プロバイダーをロードして、リクエストをガイドします。 Laravelアプリケーションは、アプリケーションを起動し、リクエストを基本ミドルウェアを経由させ、ルーターマッチングによりリクエストに対応するルートを見つけ、一致したルートを実行し、リクエストはルートを通ってミドルウェアに到達し、コントローラーメソッドに到達します。

概要

リクエストが最終的に対応するコントローラー メソッドに到達すると、そのミッションは基本的に完了します。コントローラー メソッドでは、入力パラメーターがリクエストから取得され、アプリケーションの特定の側面が取得されます。ビジネス ロジックが結果を取得すると、結果は Response オブジェクトに変換され、リクエストを開始したクライアントに返されます。

この記事は主に Laravel の Request オブジェクトを整理しています。主に、Laravel の Request が現在提供しているどの機能を使用すれば、Request を実装するためのビジネス コードの車輪の再発明を避けることができるかを調べる方法を皆さんに知ってもらいたいと考えています。 .メソッドはすでに提供されています。

上記がこの記事の全内容です。皆様の学習に少しでもお役に立てれば幸いです。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連する推奨事項:

Laravel コア解釈ファサード

以上がリクエストのLaravelコア解釈の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。