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
该文件中还包括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。
然后返回数据到客户端,处理输出的数据,从而进行数据展示。