thinkphp是一个快速、兼容而且简单的轻量级国产php开发框架,也是国内使用最为广泛的国产框架。诞生于2006年,历经fcs0.6.0到 thinkphp 0.9.5,历经1.0到3.0的发展。2015年发布thinkphp5.0版本。采用全新的架构思想,引入了更多的php新特性,优化了核心,减少了依赖,实现了真正的惰性加载,支持composer,并针对api开发做了大量的优化,包括路由、日志、异常、模型、数据库、模板引擎和验证等模块都已经重构。兼容php最新版本。这使得他成为框架的首选。下面也就其框架对一定的解析。
运行机制及流程
1.入口文件index.php
独立模式
define('app_path', __dir__ . '/../application/');
define('app_debug', true);require __dir__ . '/../thinkphp/start.php';
composer模式
define('app_path', __dir__ . '/../application/');
define('app_debug', true);if (is_file(__dir__ . '/../vendor/autoload.php')) { require_once __dir__ . '/../vendor/autoload.php';
} else { require __dir__ . '/../thinkphp/start.php';
}
2.框架引导文件start.php
namespace think;
// thinkphp 引导文件
// 加载基础文件
require __dir__ . '/base.php';
// 执行应用
app::run()->send();
3.全局变量文件base.php
define('think_version', '5.0.2');
//tp版本号define('think_start_time', microtime(true));
//启动时间define('think_start_mem', memory_get_usage());
//获取分配给 php 的内存量define('ext', '.php');
//文件后缀define('ds', directory_separator);
//系统分隔符defined('think_path') or define('think_path', __dir__ . ds);
//项目根目录define('lib_path', think_path . 'library' . ds);
//类库目录define('core_path', lib_path . 'think' . ds);
//核心文件目录define('trait_path', lib_path . 'traits' . ds);
//复用机制文件目录defined('app_path') or define('app_path', dirname($_server['script_filename']) . ds);
//应用根目录defined('root_path') or define('root_path', dirname(realpath(app_path)) . ds);
//根目录defined('extend_path') or define('extend_path', root_path . 'extend' . ds);
//扩展目录defined('vendor_path') or define('vendor_path', root_path . 'vendor' . ds);
//第三方库和插件放置defined('runtime_path') or define('runtime_path', root_path . 'runtime' . ds);
//运行缓存目录defined('log_path') or define('log_path', runtime_path . 'log' . ds);
//日志文件目录defined('cache_path') or define('cache_path', runtime_path . 'cache' . ds);
//缓存文件目录defined('temp_path') or define('temp_path', runtime_path . 'temp' . ds);
//临时目录defined('conf_path') or define('conf_path', app_path);
// 配置文件目录defined('conf_ext') or define('conf_ext', ext);
// 配置文件后缀defined('env_prefix') or define('env_prefix', 'php_');
// 环境变量的配置前缀
// 环境常量
define('is_cli', php_sapi == 'cli' ? true : false);
define('is_win', strpos(php_os, 'win') !== false);
// 载入loader类
require core_path . 'loader.php';
// 加载环境变量配置文件
if (is_file(root_path . '.env')) {
$env = parse_ini_file(root_path . '.env', true);
foreach ($env as $key => $val) {
$name = env_prefix . strtoupper($key);
if (is_array($val)) {
foreach ($val as $k => $v) {
$item = $name . '_' . strtoupper($k);
putenv("$item=$v");
}
} else {
putenv("$name=$val");
}
}
}
// 注册自动加载
\think\loader::register();
// 注册错误和异常处理机制
\think\error::register();
// 加载惯例配置文件
\think\config::set(include think_path . 'convention' . ext);
4.自动加载器文件loader.php
loader.php是框架的类的自动加载实现文件。可以使用autoload()自动挡加载类,import()手动加载指定目录的类。
protected static $map = []; 系统的类名映射缓存数组,在下面的addmap()使用
protected static $load = []; 系统的加载列表缓存数组,在下面的autoload()使用
protected static $namespace = []; 系统的命名空间缓存数组,在下面的addnamespace()使用
private static $prefixlengthspsr4 = [];private static $prefixdirspsr4 = [];
系统的psr-4缓存数组,在下面的registercomposerloader()使用
private static $prefixespsr0 = []; 系统的psr-0缓存数组,在下面的registercomposerloader()使用。
上面四个静态变量用作加载器的缓存数组,保证加载效率。
1 autoload($class)
根据类名自动加载。
public static function autoload($class){}
使用类库映射加载对应的类。
if (isset(self::$map[$class])) { if (is_file(self::$map[$class])) {
app_debug && self::$load[] = self::$map[$class]; include self::$map[$class];
}
}
使用composer加载类
elseif ($file = self::findfileincomposer($class)) {
app_debug && self::$load[] = $file; include $file;
}
根据命名空间自动加载类
else { if (!strpos($class, '\\')) { return;
} list($name, $class) = explode('\\', $class, 2);
if (isset(self::$namespace[$name])) { $path = self::$namespace[$name];
} elseif (is_dir(extend_path . $name)) { $path = extend_path . $name . ds;
} else { return;
} $filename = $path . str_replace('\\', ds, $class) . ext;
if (is_file($filename)) { if (app_debug && is_win && false === strpos(realpath($filename), $class . ext)) { return;
}
app_debug && self::$load[] = $filename; include $filename;
} else {
log::record('autoloader error : ' . $filename, 'notice');
}
}
2 addmap($class,$map='')
注册类名映射
public static function addmap($class, $map = ''){} 数组合并到$map,字符串关联到$class.
if (is_array($class)) { self::$map = array_merge(self::$map, $class);
} else { self::$map[$class] = $map;
}
3 addnamespace($namespace,$path)
注册命名空间和路径的关联
public static function addnamespace($namespace, $path = ''){} 数组合并到$namespace,字符串关联到path.
if (is_array($namespace)) { self::$namespace = array_merge(self::$namespace, $namespace);
} else { self::$namespace[$namespace] = $path;
}
4 register($autoload='')
注册自动加载机制
public static function register($autoload = ''){} think\loader::autoload()系统自动加载
self::registercomposerloader() composer自动加载
spl_autoload_register($autoload ? $autoload : 'think\\loader::autoload');self::registercomposerloader();
5 composer自动加载的注册
private static function registercomposerloader(){} 关于composer自动加载机制见 基础原理的php的composer自动加载
6 composer自动加载的两个私有方法
private static function composerrequire($fileidentifier, $file){}private static function findfileincomposer($class, $ext = '.php'){}
7 import($class,$baseurl='',$ext=ext)
手动加载$baseurl下的$class命名的$ext后缀文件
public static function import($class, $baseurl = '', $ext = ext){} 首先分析$baseurl,
然后查找$baserurl.$class.$ext 文件名,然后加载对应文件
以上就是php框架设计之thinkphp5源码解析一的内容。