深入ThinkPHP5的源码研究,tp5是如何从网站开始运行起来的?

1.解析器配置,指定路径

首先我们在nginx 或者 apache的配置文件中指定了该项目的路径是到public。

eg:nginx:

server
{
    listen 80;
    #listen [::]:80 default_server ipv6only=on;
    server_name www.t5.cn;
    index index.html index.htm index.php;
    root  /home/wwwroot/tp5/public;
    ....

 

2.index.php

然后网站解析就会达到public,由于默认文件为index.php.html.htm,所以进入了index.php文件。在该文件中有个定义常量,我们也可以定义属于自己的常量,从而在项目中引用。(这里可能有萌新会发现有个__DIR__没有被定义常量却被引用了? 其实 __DIR__ 为魔术方法,获取当前执行的PHP脚本所在的目录 ../application/)

 

3.start.php

在这里,他加载了base.php,并执行了  App::run()->send();  那就让我们到  __DIR__ . '/base.php'  去找一下这个静态函数。

 

4.base.php   

在这里边定义了很多的路径常量 和 基本配置,这里给大家说两个以后可能会用到的:

define('EXT', '.php');
define('DS', DIRECTORY_SEPARATOR);

第一个是定义了.php后缀。第二个是路径分隔符,也就是把windows上的"\” 换成"linux上的 "/"。

然后最重要的就是:

require CORE_PATH . 'Loader.php'; 

 

5.Loader.php     引入 :自动加载

这是最重要的:spl_autoload_register  实现类的自动加载,下边有两个例子,分别是tp5和yii2

深入ThinkPHP5的源码研究,tp5是如何从网站开始运行起来的?_第1张图片

深入ThinkPHP5的源码研究,tp5是如何从网站开始运行起来的?_第2张图片

 

该文件中还包括PSR-4,cli环境,自动加载autoload,db等静态方法;

PSR-4:使代码更加规范,能够满足面向package的自动加载,它规范了如何从文件路径自动加载类,同时规范了自动加载文件的位置。(简单点说,就是 模块--控制器--操作  这三步的实现方法)

cli环境:CLI则是命令行接口,用于在操作系统命令行模式下执行PHP,比如可以直接在win的cmd或Linux的shell模式下直接输入 php a.php 来得到结果。

db()这些函数就是我们常用的了,他的运行代码就在loader里包含了,我们要用,就只需要在控制层   use think\Db;  就好了。

在这个文件中我们能看到好多他

(DB.PHP 用的单例设计模式哦)

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

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

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

配置准备工作都好了,让我们反过头看3中的App::run()->send();

 

6.App.php

这个文件是在thinkphp/think/下。打开你会发现,他的USE

use think\exception\ClassNotFoundException;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\RouteNotFoundException;

我们可以看出这些都是以前存放某方法的配置文件,所以app.php是config.php的底层文件;

接着我们找run的方法:

public static function run(Request $request = null)
    {
        $request = is_null($request) ? Request::instance() : $request;

        try {
            $config = self::initCommon();

            // 模块/控制器绑定
            if (defined('BIND_MODULE')) {
                BIND_MODULE && Route::bind(BIND_MODULE);
            } elseif ($config['auto_bind_module']) {
                // 入口自动绑定
                $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
                if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
                    Route::bind($name);
                }
            }

            $request->filter($config['default_filter']);
            
            ......

    }

这只是我截取的其中一段,这里需要注意:BIND_MODULE。这个常量一般不会用到,如果想用,一般请在index.php中定义,它的作用定义了模块的名字。

入口文件的程序,默认是 index--index--index。这是因为我们没有改配置,我们可以在config.php中修改:

    // 默认模块名
    'default_module'         => 'index',
    // 禁止访问模块
    'deny_module_list'       => ['common'],
    // 默认控制器名
    'default_controller'     => 'Index',
    // 默认操作名
    'default_action'         => 'index',

当然了也可以直接定义常量去修改模块的名字,比如我们  define('BIND_MODULE', '.home'); 那么confing中的这个模块就会失效,从而流程变为 home--index--index。

-------------------------------------------------------------------分割线-----------------------------------------------------------------------------------

在上边的run函数中,我们发现他还调用了自己的静态方法:exec():

protected static function exec($dispatch, $config)
    {
        switch ($dispatch['type']) {
            case 'redirect': // 重定向跳转
                $data = Response::create($dispatch['url'], 'redirect')
                    ->code($dispatch['status']);
                break;
            case 'module': // 模块/控制器/操作
                $data = self::module(
                    $dispatch['module'],
                    $config,
                    isset($dispatch['convert']) ? $dispatch['convert'] : null
                );
                break;
            case 'controller': // 执行控制器操作
                $vars = array_merge(Request::instance()->param(), $dispatch['var']);
                $data = Loader::action(
                    $dispatch['controller'],
                    $vars,
                    $config['url_controller_layer'],
                    $config['controller_suffix']
                );
                break;
            case 'method': // 回调方法
                $vars = array_merge(Request::instance()->param(), $dispatch['var']);
                $data = self::invokeMethod($dispatch['method'], $vars);
                break;
            case 'function': // 闭包
                $data = self::invokeFunction($dispatch['function']);
                break;
            case 'response': // Response 实例
                $data = $dispatch['response'];
                break;
            default:
                throw new \InvalidArgumentException('dispatch type not support');
        }

        return $data;
    }

该方法是先判断是否有重定向,有的话就跳到重定向。接下来判断进入哪个文件,比如: index--index--index。

然后返回数据到客户端,处理输出的数据,从而进行数据展示。

你可能感兴趣的:(php后端,tp5框架)