Skip to content

详细说明

php
//第一步:实例App.php App.php又是继承 Container.php得到,最终行到一个App对象
namespace think;
require __DIR__ . '/../vendor/autoload.php';
(new App())
//第二步:(new App())->http 通过__get()来动态加载Http.php类型
$http = (new App())->http;
//第三步:(new App())->http->run() 通过run()方法运行整个http处理过程,最终返加一个$response对象
$response = $http->run();
//第四步:$response返回到浏览器
$response->send();
//第五步:处理日志的写入
$http->end($response);
  • 第一步分析:命名空间为think,使用composer规则加载一个公共文件,这样只要使用composer安装的库都能自动引入,由于thinkphp的核心库使用的是think命名空间,这样就可以使用thinkphp核心库的类了,这样就执行了App实例(new App()),这里面实例可以通过get_include_files()方法查看加载的文件情况。要对composer做一些基本的了解:https://learnku.com/docs/composer/2018
json
 {
    "autoload": {
        //自动加载引入的文件目录
        "psr-4": {
            "think\\": "src"
        },
        //加载引入文件,会放到autoload_static.php文件中,会提前加载在(new App())实例前
        "files": [
            "src/helper.php"
        ]
    },
 }

new App(),这样其实就是实例一个App类,执行了App中的__construct()方法

php
 public function __construct(string $rootPath = '')
{
        $this->thinkPath   = realpath(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
        $this->rootPath    = $rootPath ? rtrim($rootPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
        $this->appPath     = $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
        $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;

        if (is_file($this->appPath . 'provider.php')) {
            $this->bind(include $this->appPath . 'provider.php');
        }

        static::setInstance($this);

        $this->instance('app', $this);
        $this->instance('think\Container', $this);
}
  • 第二步分析:获取到一个http实例,其实是用到了App.php是继承Container.php,Container.php文件中有一个魔术方法__get(),这个方法是PHP中一个多态的实现方式,这样可以使用框架内的类型动态加载到框架中,
php
//这里是调用了get方法
 public function __get($name)
{
    return $this->get($name);
}
//get方法中返回了一个make方法
public function get($abstract)
{
    if ($this->has($abstract)) {
        return $this->make($abstract);
    }

    throw new ClassNotFoundException('class not exists: ' . $abstract, $abstract);
}
//make方法是返回了一个Http.php实例
public function make(string $abstract, array $vars = [], bool $newInstance = false)
{
    $abstract = $this->getAlias($abstract);

    if (isset($this->instances[$abstract]) && !$newInstance) {
        return $this->instances[$abstract];
    }

    if (isset($this->bind[$abstract]) && $this->bind[$abstract] instanceof Closure) {
        $object = $this->invokeFunction($this->bind[$abstract], $vars);
    } else {
        $object = $this->invokeClass($abstract, $vars);
    }

    if (!$newInstance) {
        $this->instances[$abstract] = $object;
    }

    return $object;
}
  • 第三步分析:得到Http.php类后可以使用类中的run()方法运行整个http的处理,处理完成后交到下一步去返回内容
php
public function run(Request $request = null): Response
{
    //初始化
    $this->initialize();

    //自动创建request对象
    $request = $request ?? $this->app->make('request', [], true);
    $this->app->instance('request', $request);

    try {
        $response = $this->runWithRequest($request);
    } catch (Throwable $e) {
        $this->reportException($e);

        $response = $this->renderException($request, $e);
    }

    return $response;
}

此过程是整个最核心部分,路由处理,中间处理,参数处理,事件处理等等都这里面,这个只有慢慢的去看了

  • 第四步分析:就是执行了Http.php类中的方法send(),这一步就是把处理后的内容返回到客户端
php
//send()方法最终执行senData()方法
public function send(): void
{
        // 处理输出数据
    $data = $this->getContent();

    if (!headers_sent()) {
        if (!empty($this->header)) {
                // 发送状态码
            http_response_code($this->code);
                // 发送头部信息
            foreach ($this->header as $name => $val) {
                header($name . (!is_null($val) ? ':' . $val : ''));
            }
        }

        if ($this->cookie) {
            $this->cookie->save();
        }
    }

    $this->sendData($data);

    if (function_exists('fastcgi_finish_request')) {
            // 提高页面响应
        fastcgi_finish_request();
    }
}
//sendData()就是返回数据
protected function sendData(string $data): void
 {
    echo $data;
}

第五步分析:end()方法的功能就是写日志

php
public function end(Response $response): void
{
    $this->app->event->trigger(HttpEnd::class, $response);

    //执行中间件
    $this->app->middleware->end($response);

    // 写入日志
    $this->app->log->save();
}

Released under the MIT License.