Laravel core interpretation of Request

不言
Release: 2023-04-02 17:10:01
Original
4047 people have browsed it

This article mainly introduces the core interpretation of Laravel Request, which has certain reference value. Now I share it with everyone. Friends in need can refer to it

Request

Many frameworks will Requests from the client are abstracted into classes for easy use by applications, and Laravel is no exception. The Illuminate\Http\Request class is an abstraction of client requests in the Laravel framework. It is built on the Request component provided by the Symfony framework. Today's article will briefly take a look at how Laravel creates a Request object. I won't go into too much detail about the capabilities that the Request object provides for applications. After I finish explaining the creation process, you will know where to go to the source code. Look for the methods provided by the Request object. Some cheat sheets on the Internet list some methods provided by Request, but they are not complete and some of them are not explained. Therefore, I still recommend that if you are curious about whether Request has achieved the capabilities you want during development. Go to the source code of Request to see if there is a corresponding method. The execution results of each method are clearly marked in the method comments. Let’s get to the point.

Creating the Request object

We can see in the index.php file of the Laravel application that the Request object has been created before the Laravel application is officially started. 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()
);
Copy after login

The client's HTTP request is an object of the Illuminate\Http\Request class

class Request extends SymfonyRequest implements Arrayable, ArrayAccess
{
    //新建Request实例
    public static function capture()
    {
        static::enableHttpMethodParameterOverride();

        return static::createFromBase(SymfonyRequest::createFromGlobals());
    }
}
Copy after login

through the Illuminate\Http\Request class You can see from the source code that it inherits from the Symfony Request class, so many functions implemented in the Illuminate\Http\Request class are provided by Symfony Reques Function-based implementation. From the above code, you can see that the capture method also relies on the instance of the Symfony Request class when creating a new Request object.

namespace Symfony\Component\HttpFoundation;
class Request
{
    /**
     * 根据PHP提供的超级全局数组来创建Smyfony Request实例
     *
     * @return static
     */
    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.
        $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 = 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;
    }
    
}
Copy after login

There is one point in the above code that requires additional explanation. Starting from PHP5.4, PHP's built-in web server can be started through the command line interpreter, for example:

php -S localhost:8000 -t htdocs

-S <addr>:<port> Run with built-in web server.
-t <docroot>     Specify document root <docroot> for built-in web server.
Copy after login

But the built-in web server has a bug that stores the two request headers CONTENT_LENGTH and CONTENT_TYPE In HTTP_CONTENT_LENGTH and HTTP_CONTENT_TYPE, special processing is done here in order to unify the request header fields in the built-in server and the real server.

Symfony Request instances are created through super global arrays in PHP. These super global arrays include $_GET, $_POST, $ _COOKIE, $_FILES, $_SERVER cover all super global arrays related to HTTP requests in PHP. When creating a Symfony Request instance, the Symfony Package will be created based on these global arrays. Provided ParamterBag ServerBag FileBag HeaderBag instances. These Bags are access and setting APIs provided by Symfony for different HTTP components. Readers who are interested in these examples of ParamterBag provided by Symfony can check out the source code themselves. I won’t go into details here.

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->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->request = new ParameterBag($request);
        $this->query = new ParameterBag($query);
        $this->attributes = new ParameterBag($attributes);
        $this->cookies = new ParameterBag($cookies);
        $this->files = new FileBag($files);
        $this->server = new ServerBag($server);
        $this->headers = new HeaderBag($this->server->getHeaders());

        $this->content = $content;
        $this->languages = null;
        $this->charsets = null;
        $this->encodings = null;
        $this->acceptableContentTypes = null;
        $this->pathInfo = null;
        $this->requestUri = null;
        $this->baseUrl = null;
        $this->basePath = null;
        $this->method = null;
        $this->format = null;
    }
    
}
Copy after login

You can see that the Symfony Request class has many attributes in addition to the ones mentioned above. These attributes together form a complete abstraction of HTTP requests. We can easily access them through instance attributesMethod, Charset and other attributes of these HTTP requests.

After getting the Symfony Request instance, Laravel will clone the instance and reset some of its properties:

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;
    }
Copy after login

After the Request object is created, we can easily apply it in the Laravel application. When using the Request object, if you don’t know whether it achieves the function you want, it is very simple to go directly to the source code file of Illuminate\Http\Request to check it. All methods are listed In this source code file, for example:

/**
 * Get the full URL for the request.
 * 获取请求的URL(包含host, 不包括query string)
 *
 * @return string
 */
public function fullUrl()
{
    $query = $this->getQueryString();

    $question = $this->getBaseUrl().$this->getPathInfo() == &#39;/&#39; ? &#39;/?&#39; : &#39;?&#39;;

    return $query ? $this->url().$question.$query : $this->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->getBaseUrl().$this->getPathInfo() == &#39;/&#39; ? &#39;/?&#39; : &#39;?&#39;;

    return count($this->query()) > 0
        ? $this->url().$question.http_build_query(array_merge($this->query(), $query))
        : $this->fullUrl().$question.http_build_query($query);
}
Copy after login

The station that Request passes through

After creating the Request object, Laravel's Http Kernel will continue to execute: load the service provider to guide the Laravel application, Start the application, let the Request pass through the basic middleware, find the route corresponding to the Request through Router matching, execute the matched route, and the Request goes up to the middleware through the route to reach the controller method.

Summary

As the Request finally reaches the corresponding controller method, its mission is basically completed. In the controller method, the input parameters are obtained from the Request and then certain aspects of the application are executed. Once the business logic obtains the result, the result will be converted into a Response object and returned to the client that initiated the request.

This article mainly sorts out the Request object in Laravel. It mainly wants everyone to know how to find out what capabilities Request in Laravel currently provides for us to use to avoid reinventing the wheel in the business code to implement Request. methods already provided.

The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!

Related recommendations:

The above is the detailed content of Laravel core interpretation of Request. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!