/**
* 初始化运行环境
*
* @param callable $initDi 注入依赖
*/
private static function init($initDi)
{
define('CML_PATH', dirname(__DIR__));
//框架的路径
define('CML_CORE_PATH', CML_PATH . DIRECTORY_SEPARATOR . 'Cml');
// 系统核心类库目录
define('CML_EXTEND_PATH', CML_PATH . DIRECTORY_SEPARATOR . 'Vendor');
// 系统扩展类库目录
self::handleConfigLang();
//后面自动载入的类都会自动收集到Debug类下
spl_autoload_register('Cml\\Cml::autoloadComposerAdditional', true, true);
//初始化依赖
$initDi();
//包含框架中的框架函数库文件
Cml::requireFile(CML_CORE_PATH . DIRECTORY_SEPARATOR . 'Tools' . DIRECTORY_SEPARATOR . 'functions.php');
//设置自定义捕获致命异常函数
//普通错误由Cml\Debug::catcher捕获 php默认在display_errors为On时致命错误直接输出 为off时 直接显示服务器错误或空白页,体验不好
register_shutdown_function(function () {
if ($error = error_get_last()) {
//获取最后一个发生的错误的信息。 包括提醒、警告、致命错误
if (in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING])) {
//当捕获到的错误为致命错误时 报告
if (Plugin::hook('cml.before_fatal_error', $error) == 'jump') {
return;
}
Cml::getContainer()->make('cml_error_or_exception')->fatalError($error);
Plugin::hook('cml.after_fatal_error', $error);
}
}
Plugin::hook('cml.before_cml_stop');
});
//捕获致命异常
//设置自定义的异常处理函数。
set_exception_handler(function ($e) {
if (Plugin::hook('cml.before_throw_exception', $e) === 'resume') {
return;
}
Cml::getContainer()->make('cml_error_or_exception')->appException($e);
});
//手动抛出的异常由此函数捕获
ini_set('display_errors', 'off');
//屏蔽系统自带的错误输出
//载入插件配置文件
$pluginConfig = Cml::getApplicationDir('global_config_path') . DIRECTORY_SEPARATOR . 'plugin.php';
is_file($pluginConfig) && Cml::requireFile($pluginConfig);
Plugin::hook('cml.before_set_time_zone');
//用于动态设置时区等。
date_default_timezone_set(Config::get('time_zone'));
//设置时区
self::$nowTime = time();
self::$nowMicroTime = microtime(true);
//全局的自定义语言包
$globalLang = Cml::getApplicationDir('global_lang_path') . DIRECTORY_SEPARATOR . Config::get('lang') . '.php';
is_file($globalLang) && Lang::set(Cml::requireFile($globalLang));
//设置调试模式
if (Cml::$debug) {
Debug::start();
//记录开始运行时间\内存初始使用
//设置捕获系统异常 使用set_error_handler()后,error_reporting将会失效。所有的错误都会交给set_error_handler。
set_error_handler('\\Cml\\Debug::catcher');
Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Cml'), Debug::TIP_INFO_TYPE_INCLUDE_LIB);
Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Config'), Debug::TIP_INFO_TYPE_INCLUDE_LIB);
Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Lang'), Debug::TIP_INFO_TYPE_INCLUDE_LIB);
Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Http\\Request'), Debug::TIP_INFO_TYPE_INCLUDE_LIB);
Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Debug'), Debug::TIP_INFO_TYPE_INCLUDE_LIB);
$runTimeClassList = null;
} else {
$GLOBALS['debug'] = false;
//关闭debug
//ini_set('error_reporting', E_ALL & ~E_NOTICE);//记录除了notice之外的错误
ini_set('log_errors', 'off');
//关闭php自带错误日志
//严重错误已经通过fatalError记录。为了防止日志过多,默认不记录致命错误以外的日志。有需要可以修改配置开启
if (Config::get('log_warn_log')) {
set_error_handler('\\Cml\\Log::catcherPhpError');
}
//线上模式包含runtime.php
$runTimeFile = Cml::getApplicationDir('global_store_path') . DIRECTORY_SEPARATOR . '_runtime_.php';
if (!is_file($runTimeFile)) {
//程序运行必须的类
$runTimeClassList = [CML_CORE_PATH . DIRECTORY_SEPARATOR . 'Controller.php', CML_CORE_PATH . DIRECTORY_SEPARATOR . 'Http' . DIRECTORY_SEPARATOR . 'Response.php', CML_CORE_PATH . DIRECTORY_SEPARATOR . 'Route.php', CML_CORE_PATH . DIRECTORY_SEPARATOR . 'Secure.php'];
Config::get('session_user') && ($runTimeClassList[] = CML_CORE_PATH . DIRECTORY_SEPARATOR . 'Session.php');
$runTimeContent = '<?php';
foreach ($runTimeClassList as $file) {
$runTimeContent .= str_replace(['<?php', '?>'], '', php_strip_whitespace($file));
}
file_put_contents($runTimeFile, $runTimeContent, LOCK_EX);
$runTimeContent = null;
}
Cml::requireFile($runTimeFile);
}
if (Request::isCli()) {
RunCliCommand::runCliCommand();
} else {
header('X-Powered-By:CmlPHP');
// 页面压缩输出支持
if (Config::get('output_encode')) {
$zlib = ini_get('zlib.output_compression');
if (empty($zlib)) {
///@ob_end_clean () ; //防止在启动ob_start()之前程序已经有输出(比如配置文件尾多敲了换行)会导致服务器303错误
ob_start('ob_gzhandler') || ob_start();
define('CML_OB_START', true);
} else {
define('CML_OB_START', false);
}
}
}
Plugin::hook('cml.before_parse_url');
//载入路由
$routeConfigFile = Cml::getApplicationDir('global_config_path') . DIRECTORY_SEPARATOR . 'route.php';
is_file($routeConfigFile) && Cml::requireFile($routeConfigFile);
Cml::getContainer()->make('cml_route')->parseUrl();
//解析处理URL
Plugin::hook('cml.after_parse_url');
//载入模块配置
$modulesConfig = Cml::getApplicationDir('apps_path') . '/' . Cml::getContainer()->make('cml_route')->getAppName() . '/' . Cml::getApplicationDir('app_config_path_name') . '/' . 'normal.php';
is_file($modulesConfig) && Config::set(Cml::requireFile($modulesConfig));
//载入模块语言包
$appLang = Cml::getApplicationDir('apps_path') . '/' . Cml::getContainer()->make('cml_route')->getAppName() . '/' . Cml::getApplicationDir('app_lang_path_name') . '/' . Config::get('lang') . '.php';
is_file($appLang) && Lang::set(Cml::requireFile($appLang));
}