thinkphp请求的处理流程

这里我们使用5.0的版本做介绍,thinkphp的git: https://github.com/top-think/think.git 看最新版本已经到6.0了,更新的很快,但核心没有太大区别。
首先看入口文件 index.php,代码如下

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

namespace think;

// ThinkPHP 引导文件
// 1. 加载基础文件
require __DIR__ . '/base.php';

// 2. 执行应用
App::run()->send();

加载了base.php,我们打开base.php文件会发现,除了定义一些全局变量之外,只有三行逻辑代码

// 注册自动加载
\think\Loader::register();

// 注册错误和异常处理机制
\think\Error::register();

// 加载惯例配置文件
\think\Config::set(include THINK_PATH . 'convention' . EXT);

而这三处代码,分别是注册自动加载,注册错误和异常处理机制,加载配置文件。这些我们可以先不用管,因为与请求并不直接相关,继续看App::run->send()
php教程系列三——thinkphp介绍
其中路由检测这部分,通过加载配置文件,对请求的地址串映射到对应的方法,其中==self::exec($dispath, $config);==这个方法中的dispath是由路由检测返回的,用于查找到Controller及Action.
在处理返回数据中,使用到了Response这个类,根据返回类型不同去实例化不同的子类,default_ajax_returndefault_return_type,在我使用的版本中有Jsonp, Json, Redirect, View, Xml这几个类,都是从Response继承来的。
处理返回数据的时候有这么几行代码
App.php function run()

// 输出数据到客户端
        if ($data instanceof Response) {
            $response = $data;
        } elseif (!is_null($data)) {
            // 默认自动识别响应输出类型
            $type = $request->isAjax() ?
            Config::get('default_ajax_return') :
            Config::get('default_return_type');

            $response = Response::create($data, $type);
        } else {
            $response = Response::create();
        }

Response.php create()

/**
     * 创建Response对象
     * @access public
     * @param mixed  $data    输出数据
     * @param string $type    输出类型
     * @param int    $code
     * @param array  $header
     * @param array  $options 输出参数
     * @return Response|JsonResponse|ViewResponse|XmlResponse|RedirectResponse|JsonpResponse
     */
    public static function create($data = '', $type = '', $code = 200, array $header = [], $options = [])
    {
        $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst(strtolower($type));
        if (class_exists($class)) {
            $response = new $class($data, $code, $header, $options);
        } else {
            $response = new static($data, $code, $header, $options);
        }

        return $response;
    }
    /**
     * 发送数据到客户端
     * @access public
     * @return mixed
     * @throws \InvalidArgumentException
     */
    public function send()
    {
        // 监听response_send
        Hook::listen('response_send', $this);

        // 处理输出数据
        $data = $this->getContent();

        // Trace调试注入
        if (Env::get('app_trace', Config::get('app_trace'))) {
            Debug::inject($this, $data);
        }

        if (200 == $this->code) {
            $cache = Request::instance()->getCache();
            if ($cache) {
                $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
                $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
                $this->header['Expires']       = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
                Cache::tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]);
            }
        }

        if (!headers_sent() && !empty($this->header)) {
            // 发送状态码
            http_response_code($this->code);
            // 发送头部信息
            foreach ($this->header as $name => $val) {
                if (is_null($val)) {
                    header($name);
                } else {
                    header($name . ':' . $val);
                }
            }
        }
		//====注意这里是输出部分====
        echo $data;

        if (function_exists('fastcgi_finish_request')) {
            // 提高页面响应
            fastcgi_finish_request();
        }

        // 监听response_end
        Hook::listen('response_end', $this);

        // 清空当次请求有效的数据
        if (!($this instanceof RedirectResponse)) {
            Session::flush();
        }
    }
    /**
     * 获取输出数据
     * @return mixed
     */
    public function getContent()
    {
        if (null == $this->content) {
            $content = $this->output($this->data);

            if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
                $content,
                '__toString',
            ])
            ) {
                throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
            }

            $this->content = (string) $content;
        }
        return $this->content;
    }

如果要返回指定格式的web内容,我们只需要从Response继承出子类,重写output函数即可。
到这里请求的处理流程就梳理完了,介绍这些内容,有助于我们后面讲解使用php进行动态数据加载,如果对处理流程不清楚的话,理解起来会有些吃力。

下期内容

使用php实现数据动态加载,以一个网站评论模块为例讲解,涉及内容较多,数据库,缓存,登录认证,验证码生成等等,需要的基本数据表有: user, site, thread, comment。基本结构如下图:
user
php教程系列三——thinkphp介绍
site
php教程系列三——thinkphp介绍
thread
php教程系列三——thinkphp介绍
comment
php教程系列三——thinkphp介绍
下一篇将详细介绍评论系统的构建

相关文章:

  • 2021-12-07
  • 2021-05-31
  • 2021-11-25
  • 2021-08-23
  • 2022-02-10
  • 2022-01-29
  • 2021-12-21
  • 2022-12-23
猜你喜欢
  • 2021-08-09
  • 2021-10-27
  • 2021-08-03
  • 2022-01-11
相关资源
相似解决方案