/** * 解析一个静态资源的内容 * */ public static function parseResourceFile() { $pathinfo = Route::getPathInfo(); array_shift($pathinfo); $resource = implode('/', $pathinfo); if (Cml::$debug) { $appName = $file = ''; $i = 0; while (true) { $resource = ltrim($resource, '/'); $pos = strpos($resource, '/'); $appName = ($appName == '' ? '' : $appName . DIRECTORY_SEPARATOR) . substr($resource, 0, $pos); $resource = substr($resource, $pos); $file = Cml::getApplicationDir('apps_path') . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR . Cml::getApplicationDir('app_static_path_name') . $resource; if (is_file($file) || ++$i >= 3) { break; } } if (is_file($file)) { Response::sendContentTypeBySubFix(substr($resource, strrpos($resource, '.') + 1)); exit(file_get_contents($file)); } else { Response::sendHttpStatus(404); } } }
/** * 命令的入口方法 * * @param array $args 传递给命令的参数 * @param array $options 传递给命令的选项 * * @return string; */ public function execute(array $args, array $options = []) { if (empty($args) || strpos($args[0], '/') < 1) { throw new \InvalidArgumentException('please input action'); } Route::setPathInfo(explode('/', trim(trim($args[0], '/\\')))); return 'don_not_exit'; }
/** * 解析一个静态资源的内容 * */ public static function parseResourceFile() { $pathinfo = Route::getPathInfo(); array_shift($pathinfo); $resource = implode('/', $pathinfo); if ($GLOBALS['debug'] && CML_IS_MULTI_MODULES) { $pos = strpos($resource, '/'); $file = CML_APP_MODULES_PATH . DIRECTORY_SEPARATOR . substr($resource, 0, $pos) . DIRECTORY_SEPARATOR . Config::get('modules_static_path_name') . substr($resource, $pos); if (is_file($file)) { Response::sendContentTypeBySubFix(substr($resource, strrpos($resource, '.') + 1)); exit(file_get_contents($file)); } else { Response::sendHttpStatus(404); } } }
/** * 解析url * * @return mixed */ public function parseUrl() { $dispatcher = \FastRoute\simpleDispatcher(function (RouteCollector $r) { foreach ($this->routes as $route) { $r->addRoute($route['method'], $route['uri'], $route['action']); } }); \Cml\Route::parsePathInfo(); $httpMethod = isset($_POST['_method']) ? strtoupper($_POST['_method']) : strtoupper($_SERVER['REQUEST_METHOD']); $routeInfo = $dispatcher->dispatch($httpMethod, implode('/', \Cml\Route::getPathInfo())); switch ($routeInfo[0]) { case Dispatcher::NOT_FOUND: case Dispatcher::METHOD_NOT_ALLOWED: break; case Dispatcher::FOUND: $_GET += $routeInfo[2]; if (is_callable($routeInfo[1])) { call_user_func($routeInfo[1]); Cml::cmlStop(); } $this->parseUrlParams($routeInfo[1]); break; } return $dispatcher; }
/** * 解析url * * @return void */ public function parseUrl() { $path = '/'; //定义URL常量 $subDir = dirname($_SERVER['SCRIPT_NAME']); if ($subDir == '/' || $subDir == '\\') { $subDir = ''; } //定义项目根目录地址 self::$urlParams['root'] = $subDir . '/'; \Cml\Route::parsePathInfo(); $pathInfo = \Cml\Route::getPathInfo(); //检测路由 if (self::$rules) { //配置了路由,所有请求通过路由处理 $isRoute = self::isRoute($pathInfo); if ($isRoute[0]) { //匹配路由成功 if (is_array($isRoute['route'])) { self::$urlParams['action'] = $isRoute['route'][2]; self::$urlParams['controller'] = $isRoute['route'][1]; $path = self::$urlParams['path'] = $isRoute['route'][0]; } else { $routeArr = explode('/', $isRoute['route']); $isRoute = null; self::$urlParams['action'] = array_pop($routeArr); self::$urlParams['controller'] = ucfirst(array_pop($routeArr)); $controllerPath = ''; while ($dir = array_shift($routeArr)) { if ($path == '/') { $path .= $dir . '/'; } else { $controllerPath .= $dir . '/'; } } self::$urlParams['controller'] = $controllerPath . self::$urlParams['controller']; unset($routeArr); } } else { self::findAction($pathInfo, $path); //未匹配到路由 按文件名映射查找 } } else { self::findAction($pathInfo, $path); //未匹配到路由 按文件名映射查找 } $pathInfo = array_values($pathInfo); for ($i = 0; $i < count($pathInfo); $i += 2) { $_GET[$pathInfo[$i]] = $pathInfo[$i + 1]; } unset($pathInfo); self::$urlParams['path'] = $path ? $path : '/'; unset($path); $_REQUEST = array_merge($_REQUEST, $_GET); }
/** * 初始化运行环境 * */ private static function init() { header('X-Powered-By:CmlPHP'); define('CML_PATH', dirname(__DIR__)); //框架的路径 //设置框架所有需要的路径 define('CML_APP_FULL_PATH', CML_PROJECT_PATH . DIRECTORY_SEPARATOR . CML_APP_PATH); define('CML_RUNTIME_PATH', CML_APP_FULL_PATH . DIRECTORY_SEPARATOR . 'Runtime'); define('CML_EXTEND_PATH', CML_PATH . DIRECTORY_SEPARATOR . 'Vendor'); // 系统扩展类库目录 //设置运行时文件路径 define('CML_RUNTIME_CACHE_PATH', CML_RUNTIME_PATH . DIRECTORY_SEPARATOR . 'Cache'); //系统缓存目录 define('CML_RUNTIME_LOGS_PATH', CML_RUNTIME_PATH . DIRECTORY_SEPARATOR . 'Logs'); //系统日志目录 define('CML_RUNTIME_DATA_PATH', CML_RUNTIME_PATH . DIRECTORY_SEPARATOR . 'Data'); //数据表的结构文件 self::handleConfigLang(); date_default_timezone_set(Config::get('time_zone')); //设置时区 self::$nowTime = time(); self::$nowMicroTime = microtime(true); //包含框架中的框架函数库文件 require CML_PATH . DIRECTORY_SEPARATOR . 'Cml' . DIRECTORY_SEPARATOR . 'Function' . DIRECTORY_SEPARATOR . 'function.php'; // 注册AUTOLOAD方法 //spl_autoload_register('Cml\Cml::autoload'); //设置自定义捕获致命异常函数 //普通错误由Cml\Debug::catcher捕获 php默认在display_errors为On时致命错误直接输出 为off时 直接显示服务器错误或空白页,体验不好 register_shutdown_function('Cml\\Cml::fatalError'); //捕获致命异常 //设置自定义的异常处理函数。 set_exception_handler('Cml\\Cml::appException'); //手动抛出的异常由此函数捕获 ini_set('display_errors', 'off'); //屏蔽系统自带的错误输出 //程序运行必须的类 $runTimeClassList = array(CML_PATH . DIRECTORY_SEPARATOR . 'Cml' . DIRECTORY_SEPARATOR . 'Controller.php', CML_PATH . DIRECTORY_SEPARATOR . 'Cml' . DIRECTORY_SEPARATOR . 'Http' . DIRECTORY_SEPARATOR . 'Response.php', CML_PATH . DIRECTORY_SEPARATOR . 'Cml' . DIRECTORY_SEPARATOR . 'Route.php', CML_PATH . DIRECTORY_SEPARATOR . 'Cml' . DIRECTORY_SEPARATOR . 'Secure.php'); Config::get('session_user') && ($runTimeClassList[] = CML_PATH . DIRECTORY_SEPARATOR . 'Cml' . DIRECTORY_SEPARATOR . 'Session.php'); //设置调试模式 if (Config::get('debug')) { $GLOBALS['debug'] = true; //开启debug Debug::start(); //记录开始运行时间\内存初始使用 //设置捕获系统异常 使用set_error_handler()后,error_reporting将会失效。所有的错误都会交给set_error_handler。 set_error_handler('\\Cml\\Debug::catcher'); spl_autoload_register('Cml\\Cml::autoloadComposerAdditional', true, true); //包含程序运行必须的类 foreach ($runTimeClassList as $file) { require $file; Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\' . basename($file)), 1); } Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Debug'), 1); $runTimeClassList = null; Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Cml'), 1); Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Config'), 1); Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Lang'), 1); Debug::addTipInfo(Lang::get('_CML_DEBUG_ADD_CLASS_TIP_', 'Cml\\Http\\Request'), 1); } 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_RUNTIME_PATH . DIRECTORY_SEPARATOR . '_runtime_.php'; if (!is_file($runTimeFile)) { $runTimeContent = '<?php'; foreach ($runTimeClassList as $file) { $runTimeContent .= str_replace(array('<?php', '?>'), '', php_strip_whitespace($file)); } file_put_contents($runTimeFile, $runTimeContent, LOCK_EX); $runTimeContent = null; } require $runTimeFile; } // 页面压缩输出支持 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); } } //包含应用函数库文件 都使用composer去管理 //$projectFuns = CML_APP_FULL_PATH.DIRECTORY_SEPARATOR.'Function'.DIRECTORY_SEPARATOR.'function.php'; //is_file($projectFuns) && require $projectFuns; //载入插件配置文件 $pluginConfig = CML_APP_FULL_PATH . DIRECTORY_SEPARATOR . 'Config' . DIRECTORY_SEPARATOR . 'plugin.php'; is_file($pluginConfig) && (require $pluginConfig); Request::isCli() && RunCliCommand::runCliCommand(); Plugin::hook('cml.before_parse_url'); //载入路由 $routeConfigFile = CML_APP_FULL_PATH . DIRECTORY_SEPARATOR . 'Config' . DIRECTORY_SEPARATOR . 'route.php'; is_file($routeConfigFile) && (require $routeConfigFile); Route::parseUrl(); //解析处理URL Plugin::hook('cml.after_parse_url'); //载入模块配置 if (CML_IS_MULTI_MODULES) { $modulesConfig = CML_APP_MODULES_PATH . Route::$urlParams['path'] . 'Config' . DIRECTORY_SEPARATOR . 'normal.php'; is_file($modulesConfig) && Config::set(require $modulesConfig); //载入模块语言包 $appLang = CML_APP_MODULES_PATH . Route::$urlParams['path'] . 'Lang' . DIRECTORY_SEPARATOR . Config::get('lang') . '.php'; is_file($appLang) && Lang::set(require $appLang); } //设置应用路径 define('CML_APP_CONTROLLER_PATH', CML_APP_MODULES_PATH . (CML_IS_MULTI_MODULES ? Route::$urlParams['path'] . 'Controller' . DIRECTORY_SEPARATOR : DIRECTORY_SEPARATOR . 'Controller' . Route::$urlParams['path'])); }