各类知识收集,PHP技术分享与解决方案各类知识收集,PHP技术分享与解决方案各类知识收集,PHP技术分享与解决方案

Str Tom,为分享PHP技术和解决方案,贡献一份自己的力量!
收藏本站(不迷路),每天更新好文章!
当前位置:首页 > CMS教程 > PHP

Laravel核心解读Request

管理员 2023-09-05
PHP
118

Laravel核心解读Request

内容导读

收集整理的这篇技术教程文章主要介绍了Laravel核心解读Request,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8960字,纯文字阅读大概需要13分钟

内容图文

这篇文章主要介绍了关于Laravel核心解读Request,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

Request

很多框架都会将来自客户端的请求抽象成类方便应用程序使用,在Laravel中也不例外。IlluminateHttpRequest类在Laravel框架中就是对客户端请求的抽象,它是构建在Symfony框架提供的Request组件基础之上的。今天这篇文章就简单来看看Laravel是怎么创建请求Request对象的,而关于Request对象为应用提供的能力我并不会过多去说,在我讲完创建过程后你也就知道去源码哪里找Request对象提供的方法了,网上有些速查表列举了一些Request提供的方法不过不够全并且有的也没有解释,所以我还是推荐在开发中如果好奇Request是否已经实现了你想要的能力时去Request的源码里看下有没有提供对应的方法,方法注释里都清楚地标明了每个方法的执行结果。下面让我们进入正题吧。

创建Request对象

我们可以在Laravel应用程序的index.php文件中看到,在Laravel应用程序正式启动完成前Request对象就已经被创建好了:

//public/index.php$app = require_once __DIR__.'/../bootstrap/app.php';$kernel = $app->make(IlluminateContractsHttpKernel::class);$response = $kernel->handle(    //创建request对象    $request = IlluminateHttpRequest::capture());

客户端的HTTP请求是IlluminateHttpRequest类的对象

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

通过IlluminateHttpRequest类的源码可以看到它是继承自Symfony Request类的,所以IlluminateHttpRequest类中实现的很多功能都是以Symfony Reques提供的功能为基础来实现的。上面的代码就可以看到capture方法新建Request对象时也是依赖于Symfony Request类的实例的。

namespace SymfonyComponentHttpFoundation;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;    }    }

上面的代码有一处需要额外解释一下,自PHP5.4开始PHP内建的builtin web server可以通过命令行解释器来启动,例如:

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.

但是内建web server有一个bug是将CONTENT_LENGTHCONTENT_TYPE这两个请求首部存储到了HTTP_CONTENT_LENGTHHTTP_CONTENT_TYPE中,为了统一内建服务器和真正的server中的请求首部字段所以在这里做了特殊处理。

Symfony Request 实例的创建是通过PHP中的超级全局数组来创建的,这些超级全局数组有$_GET$_POST$_COOKIE$_FILES$_SERVER涵盖了PHP中所有与HTTP请求相关的超级全局数组,创建Symfony Request实例时会根据这些全局数组创建Symfony Package里提供的ParamterBag ServerBag FileBag HeaderBag实例,这些Bag都是Symfony提供地针对不同HTTP组成部分的访问和设置API, 关于Symfony提供的ParamterBag这些实例有兴趣的读者自己去源码里看看吧,这里就不多说了。

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;    }    }

可以看到Symfony Request类除了上边说到的那几个,还有很多属性,这些属性在一起构成了对HTTP请求完整的抽象,我们可以通过实例属性方便地访问MethodCharset等这些HTTP请求的属性。

拿到Symfony Request实例后, Laravel会克隆这个实例并重设其中的一些属性:

namespace IlluminateHttp;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;    }

Request对象创建好后在Laravel应用中我们就能方便的应用它提供的能力了,在使用Request对象时如果你不知道它是否实现了你想要的功能,很简单直接去IlluminateHttpRequest的源码文件里查看就好了,所有方法都列在了这个源码文件里,比如:

/** * 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);}

Request经过的驿站

创建完Request对象后, Laravel的Http Kernel会接着往下执行:加载服务提供器引导Laravel应用、启动应用、让Request经过基础的中间件、通过Router匹配查找Request对应的路由、执行匹配到的路由、Request经过路由上到中间件到达控制器方法。

总结

随着Request最终到达对应的控制器方法后它的使命基本上也就完成了, 在控制器方法里从Request中获取输入参数然后执行应用的某一业务逻辑获得结果,结果会被转化成Response响应对象返回给发起请求的客户端。

这篇文章主要梳理了Laravel中Request对象,主要是想让大家知道如何去查找Laravel中Request现有提供了哪些能力供我们使用避免我们在业务代码里重新造轮子去实现Request已经提供的方法。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

以上就是Laravel核心解读Request的详细内容,更多请关注Gxl网其它相关文章!

内容总结

以上是为您收集整理的Laravel核心解读Request全部内容,希望文章能够帮你解决Laravel核心解读Request所遇到的程序开发问题。 如果觉得技术教程内容还不错,欢迎将网站推荐给程序员好友。

内容备注

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

扫码关注

qrcode

QQ交谈

回顶部