//
protected config = null;
// 全局DI容器 <\Phalcon\Di>
protected di = null {
set, get
};
// 应用实例 <\Phalcon\Application> | <\Yar_Server>
protected application = null;
// 模块实例 <\PhalconPlus\Base\ModuleDef>
protected primaryModuleDef = null;
// 加载的模块实例列表 <\PhalconPlus\Base\ModuleDef>[]
protected activeModules = [];
// <\Phalcon\Debug>
protected debug = null;
// 默认运行环境
// 其实框架定义了<\PhalconPlus\Enum\RunEnv>,但考虑再三,此处不能做枚举限制
// Enum: ['dev', 'test', 'pre-production', 'production']
protected env = \PhalconPlus\Enum\RunEnv::DEV;
// 自动处理应用
protected autoHandle = true {
set, get
};
protected loadedFiles = [] {
get
};
public function __construct(string! moduleDir, string env = "")
{
// 模块目录, PrimaryModule Dir
Sys::init(moduleDir);
// 获取并初始化运行环境
if likely empty env {
// 获取php.ini中设置的env
var sysEnv = trim(get_cfg_var(Sys::ENV_NAME));
// 这里不能强约束env的值为枚举中的一个
// 你可能会有非常多的环境,只要env值和配置文件名能对应上就行
if !empty sysEnv { let this->env = sysEnv; }
} else {
let this->env = env;
}
// 如果不是生产环境,打开Debug
// 这里我们假设生产环境的env值会以"product"开头
if substr(PHP_SAPI, 0, 3) != "cli" && !\PhalconPlus\Enum\RunEnv::isInProd(this->env) {
let this->debug = new \Phalcon\Debug();
this->debug->listen();
}
// 定义全局常量
define("APP_ENV", this->env, false); // 为了兼容, 同下
define("APP_RUN_ENV", this->env, false);
define("APP_ROOT_DIR", Sys::getRootDir(), false);
define("APP_MODULE_DIR", Sys::getPrimaryModuleDir(), false); // 为了兼容, 同下
define("APP_PRI_MODULE_DIR", Sys::getPrimaryModuleDir(), false);
define("APP_ROOT_COMMON_DIR", Sys::getCommonDir(), false);
define("APP_ROOT_COMMON_LOAD_DIR", Sys::getGlobalLoadDir(), false);
define("APP_ROOT_COMMON_CONF_DIR", Sys::getGlobalConfigDir(), false);
// 加载Composer库
if likely is_file(Sys::getComposerAutoloadPath()) {
require Sys::getComposerAutoloadPath();
}
}
private function registerModule(<\PhalconPlus\Base\ModuleDef> moduleDef) -> <\PhalconPlus\Base\AbstractModule>
{
if unlikely isset(this->activeModules[moduleDef->getName()]) {
return this->activeModules[moduleDef->getName()];
}
if unlikely is_null(this->di) {
throw new \PhalconPlus\Base\Exception("DI doesn't load yet, failed to register module " . moduleDef->getName());
}
if unlikely is_null(this->config) {
throw new \PhalconPlus\Base\Exception("Config doesn't initial yet, failed to register module " . moduleDef->getName());
}
// Load PrimaryModule-Related Config and Global-Script
if moduleDef->getIsPrimary() {
// 定义工作模式
if !defined("APP_RUN_MODE") { define("APP_RUN_MODE", moduleDef->getMode(), false); }
// 获取模块配置
var moduleConf = moduleDef->getConfig();
// 合并配置,Module配置优先级更高
this->config->merge(moduleConf);
// 装载全局服务初始化文件
this->load(moduleDef->getRunMode()->getScriptPath());
}
// Implement a module from it's defintion
var module = moduleDef->impl(this->di);
// Register autoloaders and di-services
module->registerAutoloaders();
module->registerServices();
// Maintain a list of loaded modules
let this->activeModules[moduleDef->getName()] = module;
return module;
}
public function initConf() -> <\PhalconPlus\Bootstrap>
{
// 全局配置
var globalConfPath = Sys::getGlobalConfigPath();
if unlikely !is_file(globalConfPath) {
// throw new \Phalcon\Config\Exception("Global config file not exist, file position: " . globalConfPath);
// Make a warning here
error_log("PHP Notice: PhalconPlus\\Bootstrap Global config file not exists: " . globalConfPath);
let this->config = new \Phalcon\Config([]);
} else {
let this->config = new \Phalcon\Config(this->load(globalConfPath));
}
// 初始化主模块
if empty this->primaryModuleDef {
let this->primaryModuleDef = new \PhalconPlus\Base\ModuleDef(this, APP_MODULE_DIR, true);
}
// 返回对象本身
return this;
}
public function setApp(object app, boolean autoHandle = false) -> <\PhalconPlus\Bootstrap>
{
if likely empty(this->application) {
if likely (app instanceof \Phalcon\Application) || (app instanceof \Yar_Server) {
let this->application = app;
let this->autoHandle = autoHandle;
} else {
throw new \PhalconPlus\Base\Exception("Application must be instance of phalcon\\appliction or yar_server");
}
}
return this;
}
// return object | null
public function getApp() -> object | null
{
if unlikely empty(this->application) {
throw new \PhalconPlus\Base\Exception("Sorry, empty application in bootstrap");
}
return this->application;
}
// 统一入口,也可分别调用各模式入口
public function exec()
{
// 初始化配置
this->initConf();
// 主执行方法入口
var handleMethod = "exec";
let handleMethod .= this->primaryModuleDef->getMapClassName();
return call_user_func_array([this, handleMethod], func_get_args());
}
public function terminate()
{
if session_status() == PHP_SESSION_ACTIVE { session_write_close(); }
if !headers_sent() { session_id(""); }
session_unset();
let _SESSION = [];
let _POST = [];
let _GET = [];
let _SERVER = [];
let _REQUEST = [];
let _COOKIE = [];
let _FILES = [];
\Phalcon\Di::reset();
let this->di = null;
let this->config = null;
let this->application = null;
let this->loadedFiles = [];
let this->primaryModuleDef = null;
let this->activeModules = [];
}
public function __destruct()
{
this->terminate();
}
/**
* @request a uri string (for \Phalcon\Mvc\Application) or Psr\Http\Message\Request
*/
public function execModule(var request = null) -> <\PhalconPlus\Bootstrap> | <\Phalcon\Http\Response>
{
// 如果此方法被直接调用需要自己加载配置
if empty this->config { this->initConf(); }
// 初始化容器
if empty this->di {
let this->di = new \Phalcon\DI\FactoryDefault();
// 把自己注入di
this->di->setShared("bootstrap", this);
}
// Phalcon Mvc Application
if unlikely empty(this->application) {
let this->application = new \Phalcon\Mvc\Application();
}
this->application->setDI(this->di);
// 注册模块
this->registerModule(this->primaryModuleDef);
// 如果不需要handle,则直接返回
if !this->autoHandle { return this; }
// Handle
return this->application->handle(request);
}
public function execSrv() -> <\Phalcon\Http\Response> | <\PhalconPlus\Bootstrap>
{
// 如果此方法被直接调用需要自己加载配置
if empty this->config { this->initConf(); }
// 初始化容器
if empty this->di {
let this->di = new \Phalcon\DI\FactoryDefault();
this->di->setShared("bootstrap", this);
}
// 注册模块
this->registerModule(this->primaryModuleDef);
var backendSrv = null;
// Backend Server, Default is SimpleServer
if unlikely this->di->has("backendSrv") {
let backendSrv = this->di->get("backendSrv");
if ! (backendSrv instanceof \PhalconPlus\Rpc\Server\AbstractServer) {
throw new \PhalconPlus\Base\Exception("Service object(DI[\"backendSrv\"]) must be type of \\PhalconPlus\\Rpc\\Server\\AbstractServer");
}
} else {
let backendSrv = new \PhalconPlus\Rpc\Server\SimpleServer(this->di);
this->di->setShared("backendSrv", backendSrv);
}
// Yar Server
if unlikely empty(this->application) {
let this->application = new \Yar_Server(backendSrv);
}
// 如果不需要handle,则直接返回
if !this->autoHandle { return this; }
// Handle
ob_start();
this->application->handle();
var content = ob_get_clean();
var response;
let response = new \Phalcon\Http\Response();
response->setStatusCode(200, "OK");
response->setContent(content);
return response;
}
public function execTask(array argv, <\Phalcon\DI\FactoryDefault> di = null)
{
// 如果此方法被直接调用需要自己加载配置
if empty this->config { this->initConf(); }
if empty this->di {
if likely is_null(di) || ! (di instanceof \Phalcon\DI\FactoryDefault\CLI) {
let this->di = new \Phalcon\DI\FactoryDefault\CLI();
} else {
let this->di = di;
}
this->di->setShared("bootstrap", this);
}
// Phalcon Cli Application
if unlikely empty(this->application) {
let this->application = new \Phalcon\CLI\Console();
}
this->application->setDI(this->di);
// 注册模块
this->registerModule(this->primaryModuleDef);
// 如果不需要handle,则直接返回
if !this->autoHandle { return this; }
// Handle
return this->application->handle(argv);
}
public function getPrimaryModuleDef() -> <\PhalconPlus\Base\ModuleDef>
{
return this->primaryModuleDef;
}
public function getPrimaryModule() -> <\PhalconPlus\Base\AbstractModule>
{
var name = this->primaryModuleDef->getName();
if !isset(this->activeModules[name]) {
throw new \PhalconPlus\Base\Exception("Module not exists: " . name);
}
return this->activeModules[name];
}
public function getModule(string! name) -> <\PhalconPlus\Base\AbstractModule>
{
if !isset(this->activeModules[name]) {
throw new \PhalconPlus\Base\Exception("Module not exists: " . name);
}
return this->activeModules[name];
}
public function getModuleDef(string! name) -> <\PhalconPlus\Base\ModuleDef>
{
if !isset(this->activeModules[name]) {
throw new \PhalconPlus\Base\Exception("Module not exists: " . name);
}
return this->activeModules[name]->getDef();
}
public function dependModule(string! moduleName) -> <\PhalconPlus\Base\AbstractModule>
{
var module, moduleDef, moduleDir, moduleConf;
let moduleDir = Sys::getModuleDirByName(moduleName);
let moduleDef = new \PhalconPlus\Base\ModuleDef(this, moduleDir);
// 注册模块
let module = this->registerModule(moduleDef);
// 保留被依赖的模块的配置, 已经移除
// this->di->set("moduleConfig", moduleDef->getConfig());
// Use `$bootstrap->getModuleDef($moduleName)->getConfig()` instead
// 参与合并的模块配置
let moduleConf = new \Phalcon\Config(this->load(moduleDef->getConfigPath()));
// 全局配置文件优先级高于被依赖的模块
moduleConf->merge(this->config);
this->setConfig(moduleConf);
return module;
}
public function isDebug() -> boolean
{
return null != this->debug;
}
public function getDebug() -> <\Phalcon\Debug>
{
return this->debug;
}
public function getEnv() -> string
{
return this->env;
}
public function getConfig() -> <\Phalcon\Config>
{
return this->config;
}
// 传入的 Config 优先级更高
public function setConfig(<\Phalcon\Config> config)
{
var globalConf;
if ! this->di->has("config") {
let globalConf = new \Phalcon\Config();
} else {
let globalConf = this->di->getConfig();
}
globalConf->merge(config);
let this->config = globalConf;
this->di->set("config", this->config);
return this;
}
public function load(var filePath)
{
if unlikely !is_string(filePath) {
return false;
}
if unlikely !is_file(filePath) {
throw new \PhalconPlus\Base\Exception("The file you try to load is not exists. file position: " . filePath);
}
var loader, config, application, di;
var bootstrap, rootPath, fileRet;
if fetch fileRet, this->loadedFiles[filePath] {
return fileRet;
}
let
rootPath = "rootPath",
loader = "loader",
config = "config",
application = "application",
bootstrap = "bootstrap",
di = "di";
let {rootPath} = Sys::getRootDir();
let {loader} = new \Phalcon\Loader();
let {config} = this->config;
let {application} = this->application;
let {bootstrap} = this;
let {di} = this->di;
/* PHP 7.1 and later version, forbid dynamic calls to scope introspection functions
extract(["rootPath": APP_ROOT_DIR,
"loader": new \Phalcon\Loader(),
"config": this->config,
"application": this->application,
"bootstrap": this,
"di": this->di
]);
*/
let fileRet = require filePath;
let this->loadedFiles[filePath] = fileRet;
return fileRet;
}
}