Home > Article > Backend Development > Laravel core interpretation of Request
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
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.
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() );
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()); } }
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; } }
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 9581b3ba3b9ee3c707d01b5722440004:298c9bd6ad6e8c821dc63aa0473d6209 Run with built-in web server. -t ea23c61ebf6b70b26359136364366495 Specify document root ea23c61ebf6b70b26359136364366495 for built-in web server.
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; } }
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('_format') && $this->get('_format')) { $dup->attributes->set('_format', $this->get('_format')); } if (!$dup->getRequestFormat(null)) { $dup->setRequestFormat($this->getRequestFormat(null)); } return $dup; }
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() == '/' ? '/?' : '?'; 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() == '/' ? '/?' : '?'; return count($this->query()) > 0 ? $this->url().$question.http_build_query(array_merge($this->query(), $query)) : $this->fullUrl().$question.http_build_query($query); }
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.
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!