热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[李景山php]thinkphp核心源码注释|Think.class.php

<?php+----------------------------------------------------------------------|Think

// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st
// +----------------------------------------------------------------------

namespace Think;
/**
* ThinkPHP 引导类
* 开始了 最后的攻坚了
*/

class Think {

// 类映射
private static $_map = array(); // 仓库 类型

// 实例化对象
private static $_instance = array(); // 实例化 的位置

/**
* 应用程序初始化
* @access public
* @return void
*/

static public function start() { // 开始 初始了
// 第一步:先注册 各种方式。
// 注册AUTOLOAD方法
spl_autoload_register('Think\Think::autoload'); // 注册 自动执行函数
// 设定错误和异常处理
// 异常关闭
register_shutdown_function('Think\Think::fatalError'); //.也就是说当我们的脚本执行完成或意外死掉导致PHP执行即将关闭时,我们的这个函数将会 被调用.
// 错误
set_error_handler('Think\Think::appError'); // 设置 错误处理 方式
// 异常
set_exception_handler('Think\Think::appException');// 设置 异常处理 方式

// 初始化文件存储方式 第二步:文件存储
Storage::connect(STORAGE_TYPE); // 初始化文件 存储

// 第三步:缓存文件开始
$runtimefile = RUNTIME_PATH.APP_MODE.'~runtime.php'; // 初始化 生成文件 开始
if(!APP_DEBUG && Storage::has($runtimefile)){ //非调试模式
Storage::load($runtimefile); // 加载文件
}else{
// 调试模式
if(Storage::has($runtimefile))
Storage::unlink($runtimefile);// 先删掉
$content = '';// 内容 准备 出来了
// 读取应用模式
$mode = include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';// 读取 配置 文件
// 加载核心文件
foreach ($mode['core'] as $file){
if(is_file($file)) {
include $file;
if(!APP_DEBUG) $content .= compile($file);
}
}// 文件加载

// 加载应用模式配置文件
foreach ($mode['config'] as $key=>$file){
is_numeric($key)?C(load_config($file)):C($key,load_config($file));
}

// 读取当前应用模式对应的配置文件
if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.CONF_EXT))
C(load_config(CONF_PATH.'config_'.APP_MODE.CONF_EXT));

// 加载模式别名定义
if(isset($mode['alias'])){
self::addMap(is_array($mode['alias'])?$mode['alias']:include $mode['alias']);
}

// 加载应用别名定义文件
if(is_file(CONF_PATH.'alias.php'))
self::addMap(include CONF_PATH.'alias.php');

// 加载模式行为定义
if(isset($mode['tags'])) {
Hook::import(is_array($mode['tags'])?$mode['tags']:include $mode['tags']);
}

// 加载应用行为定义
if(is_file(CONF_PATH.'tags.php'))
// 允许应用增加开发模式配置定义
Hook::import(include CONF_PATH.'tags.php');

// 加载框架底层语言包
L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php');

if(!APP_DEBUG){
$content .= "\nnamespace { Think\\Think::addMap(".var_export(self::$_map,true).");";
$content .= "\nL(".var_export(L(),true).");\nC(".var_export(C(),true).');Think\Hook::import('.var_export(Hook::get(),true).');}';
Storage::put($runtimefile,strip_whitespace('.$content));
}else{
// 调试模式加载系统默认的配置文件
C(include THINK_PATH.'Conf/debug.php');
// 读取应用调试配置文件
if(is_file(CONF_PATH.'debug'.CONF_EXT))
C(include CONF_PATH.'debug'.CONF_EXT);
}
}// 加载各种 生成 文件

// 读取当前应用状态对应的配置文件
if(APP_STATUS && is_file(CONF_PATH.APP_STATUS.CONF_EXT))
C(include CONF_PATH.APP_STATUS.CONF_EXT); // 读取当前的配置,临时配置文件

// 设置系统时区
date_default_timezone_set(C('DEFAULT_TIMEZONE'));

// 检查应用目录结构 如果不存在则自动创建
if(C('CHECK_APP_DIR')) {
$module = defined('BIND_MODULE') ? BIND_MODULE : C('DEFAULT_MODULE');
if(!is_dir(APP_PATH.$module) || !is_dir(LOG_PATH)){
// 检测应用目录结构
Build::checkDir($module);
}
}// 创建 需要创建的文件

// 记录加载文件时间
G('loadTime');
// 运行应用
App::run(); // 开始运行 其它的代码了。
}// 初始化 开始

// 注册classmap
static public function addMap($class, $map=''){
if(is_array($class)){
self::$_map = array_merge(self::$_map, $class);
}else{
self::$_map[$class] = $map;
}
} // 这个 确实 是注册 classmap 开始

// 获取classmap
static public function getMap($class=''){
if(''===$class){
return self::$_map;
}elseif(isset(self::$_map[$class])){
return self::$_map[$class];
}else{
return null;
}
}// 获取了 里面的 东西了。

/**
* 类库自动加载
* @param string $class 对象类名
* @return void
* 类库依赖加载
*/

public static function autoload($class) {
// 检查是否存在映射
if(isset(self::$_map[$class])) {
include self::$_map[$class]; // 这里是这样的 包含对应的类文件的加载。
}elseif(false !== strpos($class,'\\')){ // 如果 不是 那种带有 命名空间的 里面
// echo strstr("Hello world!","world",true); 显示 hello
$name = strstr($class, '\\', true); //strstr(string,search,before_search)
if(in_array($name,array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$name)){
// Library目录下面的命名空间自动定位
$path = LIB_PATH; // 在这里的 开始 路径的准备了。
}else{
// 检测自定义命名空间 否则就以模块为命名空间
$namespace = C('AUTOLOAD_NAMESPACE'); // 模块的 命名空间了
$path = isset($namespace[$name])? dirname($namespace[$name]).'/' : APP_PATH;
}// 开始检测了
$filename = $path . str_replace('\\', '/', $class) . EXT;
// 终于找到了对应的 文件 位置
if(is_file($filename)) {
// Win环境下面严格区分大小写
if (IS_WIN && false === strpos(str_replace('/', '\\', realpath($filename)), $class . EXT)){
return ;
}
include $filename; // 包含文件
}
}elseif (!C('APP_USE_NAMESPACE')) { // 'APP_USE_NAMESPACE' => true, // 应用类库是否使用命名空间
// 自动加载的类库层
foreach(explode(',',C('APP_AUTOLOAD_LAYER')) as $layer){
if(substr($class,-strlen($layer))==$layer){
if(require_cache(MODULE_PATH.$layer.'/'.$class.EXT)) {
return ;
}
}
}// 自动 加载文件 缓存文件
// 根据自动加载路径设置进行尝试搜索
foreach (explode(',',C('APP_AUTOLOAD_PATH')) as $path){
if(import($path.'.'.$class))
// 如果加载类成功则返回
return ;
}
}
}// 总结:就是 根据 文件名 之类的 解析了 对应的 类。

/**
* 取得对象实例 支持调用类的静态方法
* @param string $class 对象类名
* @param string $method 类的静态方法名
* @return object
*/

static public function instance($class,$method='') { // 这种就是实例了
$identify = $class.$method;// 连接了
if(!isset(self::$_instance[$identify])) {
if(class_exists($class)){
$o = new $class();
if(!empty($method) && method_exists($o,$method))
self::$_instance[$identify] = call_user_func(array(&$o, $method));
else
self::$_instance[$identify] = $o;
}
else
self::halt(L('_CLASS_NOT_EXIST_').':'.$class);
}
return self::$_instance[$identify];
} // 总结:就是调用到实际里面的 method 里面的东西

/**
* 自定义异常处理
* @access public
* @param mixed $e 异常对象
*/

static public function appException($e) {
$error = array();
$error['message'] = $e->getMessage(); // 获取信息
$trace = $e->getTrace();// 获取错误信息
if('E'==$trace[0]['function']) {// 里面 开始
$error['file'] = $trace[0]['file'];
$error['line'] = $trace[0]['line'];
}else{// 对的
$error['file'] = $e->getFile(); //获取文件
$error['line'] = $e->getLine(); // 获取 line
}
$error['trace'] = $e->getTraceAsString(); // 弄成字符串
Log::record($error['message'],Log::ERR);// 日志记录
// 发送404信息
header('HTTP/1.1 404 Not Found');
header('Status:404 Not Found');
self::halt($error);// 异常开始
}

/**
* 自定义错误处理
* @access public
* @param int $errno 错误类型
* @param string $errstr 错误信息
* @param string $errfile 错误文件
* @param int $errline 错误行数
* @return void
*/

static public function appError($errno, $errstr, $errfile, $errline) {
switch ($errno) {
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
ob_end_clean();
$errorStr = "$errstr ".$errfile." 第 $errline 行.";
if(C('LOG_RECORD')) Log::write("[$errno] ".$errorStr,Log::ERR);
self::halt($errorStr);
break;
default:
$errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行.";
self::trace($errorStr,'','NOTIC');
break;
}
}// 总结: 记录 外加 报错

// 致命错误捕获
static public function fatalError() {
Log::save();
if ($e = error_get_last()) {
switch($e['type']){
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
ob_end_clean();
self::halt($e);
break;
}
}
}// 致命错误

/**
* 错误输出
* @param mixed $error 错误
* @return void
*/

static public function halt($error) {
$e = array();// 内容开始
if (APP_DEBUG || IS_CLI) {
//调试模式下输出错误信息
if (!is_array($error)) { // 这里的还要分 字符串 或者是 数组
$trace = debug_backtrace();
$e['message'] = $error;
$e['file'] = $trace[0]['file'];
$e['line'] = $trace[0]['line'];
ob_start();
debug_print_backtrace();
$e['trace'] = ob_get_clean();
} else {
$e = $error;
}
if(IS_CLI){// 直接 就开始了
exit(iconv('UTF-8','gbk',$e['message']).PHP_EOL.'FILE: '.$e['file'].'('.$e['line'].')'.PHP_EOL.$e['trace']);
}
} else {
//否则定向到错误页面
$error_page = C('ERROR_PAGE');
if (!empty($error_page)) {
redirect($error_page);// 直接 跳转
} else {
$message = is_array($error) ? $error['message'] : $error;
$e['message'] = C('SHOW_ERROR_MSG')? $message : C('ERROR_MESSAGE');
}
}
// 包含异常页面模板
$exceptionFile = C('TMPL_EXCEPTION_FILE',null,THINK_PATH.'Tpl/think_exception.tpl');
include $exceptionFile;// 包含模版 并且退出
exit;
} // 包含模版 并且退出
// 总结: 这里的 不能

/**
* 添加和获取页面Trace记录
* @param string $value 变量
* @param string $label 标签
* @param string $level 日志级别(或者页面Trace的选项卡)
* @param boolean $record 是否记录日志
* @return void|array
*/

static public function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
static $_trace = array();// 这里的 又是静态仓库了,在一次运行中,要跑这么多东西,好累啊!
if('[think]' === $value){ // 获取trace信息
return $_trace;// 也就是 默认的 返回了
}else{
$info = ($label?$label.':':'').print_r($value,true); // 这种是输出 到字符串
$level = strtoupper($level);// 转换成为了

if((defined('IS_AJAX') && IS_AJAX) || !C('SHOW_PAGE_TRACE') || $record) {
Log::record($info,$level,$record); // 记录日志
}else{
if(!isset($_trace[$level]) || count($_trace[$level])>C('TRACE_MAX_RECORD')) {
$_trace[$level] = array();
}
$_trace[$level][] = $info;
}
}
}// 这个是 记录 信息的整理了
}

推荐阅读
  • Tomcat安装与配置教程及常见问题解决方法
    本文介绍了Tomcat的安装与配置教程,包括jdk版本的选择、域名解析、war文件的部署和访问、常见问题的解决方法等。其中涉及到的问题包括403问题、数据库连接问题、1130错误、2003错误、Java Runtime版本不兼容问题以及502错误等。最后还提到了项目的前后端连接代码的配置。通过本文的指导,读者可以顺利完成Tomcat的安装与配置,并解决常见的问题。 ... [详细]
  • php缓存ri,浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
    thinkPHP的F方法只能用于缓存简单数据类型,不支持有效期和缓存对象。S()缓存方法支持有效期,又称动态缓存方法。本文是小编日常整理有关thinkp ... [详细]
  • 后端开发|php教程apache配置文件,thinkphp后端开发-php教程例如你的原路径是http:localhosttestindex.phpindexadd那么现在的地址是 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 本文介绍了关于apache、phpmyadmin、mysql、php、emacs、path等知识点,以及如何搭建php环境。文章提供了详细的安装步骤和所需软件列表,希望能帮助读者解决与LAMP相关的技术问题。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
  • PHP引用的概念和用法详解
    本文详细介绍了PHP中引用的概念和用法。引用是指不同的变量名访问同一个变量内容,类似于Unix文件系统中的hardlink。文章从引用的定义、作用、语法和注意事项等方面进行了解释和示例。同时还介绍了对未定义变量使用引用的情况,以及在函数和new运算符中使用引用的注意事项。 ... [详细]
  • 0x00端口渗透端口扫描端口的指纹信息(版本信息)端口所对应运行的服务常见的默认端口号.尝试弱口令端口爆破hydra端口弱口令NTScanHs ... [详细]
  • ThinkPHP视频教程第二十五集:关联模型
    php教程|php手册thinkphp代码,代码示例,代码参考,php短信,数据库备份代码,令牌验证,去除代码中的空白和注释Thinkphpphp教程-php手册对学习Thinkp ... [详细]
  • php 获取无限子文件,php快速无限遍历递归文件夹目录、子文件,支持绝对路径和相对路径,支持返回生成数组...
    支持无限极遍历子文件及文件夹,支持绝对路径和相对路径!函数说明:arrayglob(string$pattern[,int$flags]) ... [详细]
author-avatar
未来不是梦r
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有