Laravel5.5源碼詳解 -- Request是如何產生的?

來源:互聯網
上載者:User
Laravel5.5源碼詳解 – Request是如何產生的。

在laravel的啟動頁面,也就是public/index.php檔案內,有這麼一句,

$response = $kernel->handle(    $request = Illuminate\Http\Request::capture());

它根據瀏覽器傳入的HTTP請求,建立了一個Illuminate\Http\Request執行個體。下面,我們看一下這個執行個體的產生過程。

$request Illuminate\Http\Request::capture()

public static function capture(){    static::enableHttpMethodParameterOverride();    return static::createFromBase(SymfonyRequest::createFromGlobals());}

這裡面涉及到三個函數, A. Request::capture()調用的第1個和第2個函數

建立Request的時候,調用的相關函數如下

Vendor\Symfony\Http-foundation\Request

public static function enableHttpMethodParameterOverride(){    self::$httpMethodParameterOverride = true;}public static function createFromGlobals(){    // With the php's bug #66606, the php's built-in web server    // stores the Content-Type and Content-Length header values in    // HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields.    // 上面官方的注釋已經說明,應該有HTTP_CONTENT_TYPE 和 HTTP_CONTENT_LENGTH,但調試發現都沒有。    $server = $_SERVER;    if ('cli-server' === PHP_SAPI) {        if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) {            $server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH'];        }        if (array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) {            $server['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE'];        }    }    // 產生Request執行個體    $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server);    if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')        && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))    ) {        parse_str($request->getContent(), $data);        $request->request = new ParameterBag($data);    }    return $request;}private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null){    if (self::$requestFactory) {        $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);        if (!$request instanceof self) {            throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');        }        return $request;    }    return new static($query, $request, $attributes, $cookies, $files, $server, $content);}

最後這一句 return new static($query, $request, $attributes, $cookies, $files, $server, $content);,產生了Request的執行個體,即Symfony\Component\HttpFoundation\Request。

注意,Symfony\Http-foundation\Request的namespace是Symfony\Component\HttpFoundation; 說明一: a) $_SERVER是一個數組,它記錄了服務端的資訊,這個在伺服器啟動時生效,

array:24 [▼  "DOCUMENT_ROOT" => "D:\wamp64\www\laravel\laraveltest\public"  "REMOTE_ADDR" => "127.0.0.1"  "REMOTE_PORT" => "12492"  "SERVER_SOFTWARE" => "PHP 7.1.9 Development Server"  "SERVER_PROTOCOL" => "HTTP/1.1"  "SERVER_NAME" => "127.0.0.1"  "SERVER_PORT" => "8000"  "REQUEST_URI" => "/user/image/avatarUpload"  "REQUEST_METHOD" => "GET"  "SCRIPT_NAME" => "/index.php"  "SCRIPT_FILENAME" => "D:\wamp64\www\laravel\laraveltest\public\index.php"  "PATH_INFO" => "/user/image/avatarUpload"  "PHP_SELF" => "/index.php/user/image/avatarUpload"  "HTTP_HOST" => "localhost:8000"  "HTTP_CONNECTION" => "keep-alive"  "HTTP_CACHE_CONTROL" => "max-age=0"  "HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"  "HTTP_UPGRADE_INSECURE_REQUESTS" => "1"  "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"  "HTTP_ACCEPT_ENCODING" => "gzip, deflate, br"  "HTTP_ACCEPT_LANGUAGE" => "zh-CN,zh;q=0.9"  "HTTP_COOKIE" => "remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6ImdJRXdTZlNBbEt3a1pkM3p0OWxMTVE9PSIsInZhbHVlIjoiejZGdnZ2QlFDY0djQUN5bXd5eGpUVHgyZFUzTkV5ZTZqRVJCVE "  "REQUEST_TIME_FLOAT" => 1514626260.1018  "REQUEST_TIME" => 1514626260]
b) PHP_SAPI = ‘cli-server’,

參考, http://php.net/manual/zh/features.commandline.php

PHP可以應用在終端,也可以應用在Web伺服器中;應用在終端上的SAPI就叫做CLI SAPI,應用在Web伺服器中的就叫做CGI SAPI,在windows下安裝php的話,對應的分別是php.exe和php-cgi.exe。

在PHP中,如何得知自己使用的是哪個 SAPI。

在命令列下,運行 php -v 便能得知該 php 是 CGI 還是 CLI。請參考函數 php_sapi_name() 以及常量 PHP_SAPI。 c) $_COOKIE

特別說明一下:cookie是用戶端儲存資料的一個東西,它的作用是,當使用者登入後,後續的請求不需要再次驗證身份。原因就在於瀏覽器會在客戶的請求的頭部帶上這麼一個cookie值,這個cookie 值標明了本次請求的使用者是誰。當然,使用者不註冊登陸網站,這個cookie也是必須的,只不過裡面沒有身份資訊。

所以,當你開啟瀏覽器,輸入www.mynetwork.com時,瀏覽器會首先發出一個cookie給伺服器mynetwork.com網站的伺服器,告訴伺服器有人來瀏覽頁面了,這時候,伺服器必須響應並處理cookie(即:$_COOKIE)。

另個,各個瀏覽器的初始cookie都是不一樣的,比方說IE11是Null 字元串,Firefox的是下面這個樣子的,

array:2 [▼  "bdshare_firstime" => "1511944517485"  "remember_web_59ba36addc2b2f9401580 " => "eyJpdiI6InFBsOUZj "]
d) 其他(傳入createRequestFromFactory的)參數

目前這些參考均為空白的數組[ ],如下

$_GET, $_POST, array(), $_FILES, $server
說明二

關於Cookie管理類。

cookie管理類Illuminate\Cookie\CookieJar是在Illuminate\Cookie\CookieServiceProvider註冊時建立的,

<?phpnamespace Illuminate\Cookie;use Illuminate\Support\ServiceProvider;class CookieServiceProvider extends ServiceProvider{    public function register()    {        $this->app->singleton('cookie', function ($app) {            $config = $app->make('config')->get('session');            return (new CookieJar)->setDefaultPathAndDomain(                $config['path'],                 $config['domain'],                 $config['secure'],                 $config['same_site'] ?? null            );        });    }}
B. Request::capture()調用的第3個
public static function createFromBase(SymfonyRequest $request){    // 首先確認是不是Illuminate\Http\Request執行個體,這裡剛建立的是    // Symfony\Component\HttpFoundation, 所以if判斷為false,    if ($request instanceof static) {        return $request;    }    $content = $request->content;    // 因為不是Illuminate\Http\Request執行個體,所以這裡建立一個laravel處理的Request類的執行個體    $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;    // 有無請求參數,如果有的話,就在這裡拿(剛產生是沒有的,都從$_SERVER等參數那裡拿)    $request->request = $request->getInputSource();    return $request;}

這裡很有意思,laravel用了symfony的第三方代碼,直接把Symfony\Component\HttpFoundation對象中的一切參數拿過來,利用$request = (new static)->duplicate(...) 複製的手法,產生了一個Illuminate\Http\Request。

至此,一個完整的Illuminate\Http\Request的執行個體,$request請求產生了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.