phalconplus Documentation v1.0.0-beta
Class
Class PhalconPlus

# Bootstrap

    //
        protected config = null;
        // 全局DI容器 <\Phalcon\Di>
        protected di = null;
        // 应用实例 <\Phalcon\Mvc\Application>
        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;

        public function __construct(string! moduleDir)
        {
            // 模块目录, PrimaryModule Dir
            Sys::init(moduleDir);

            // 获取并初始化运行环境
            var env = trim(get_cfg_var(Sys::ENV_NAME));
            // 这里不能强约束env的值为枚举中的一个
            // 你可能会有非常多的环境，只要env值和配置文件名能对应上就行
            if !empty(env) {
                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, true); // 为了兼容
            define("APP_RUN_ENV", this->env, true);
            define("APP_ROOT_DIR", Sys::getRootDir(), true);
            define("APP_MODULE_DIR", Sys::getPrimaryModuleDir(), true); // 为了兼容
            define("APP_PRI_MODULE_DIR", Sys::getPrimaryModuleDir(), true);
            define("APP_ROOT_COMMON_DIR", Sys::getCommonDir(), true);
            define("APP_ROOT_COMMON_LOAD_DIR", Sys::getGlobalLoadDir(), true);
            define("APP_ROOT_COMMON_CONF_DIR", Sys::getGlobalConfigDir(), true);
        }

        private function registerModule(<\PhalconPlus\Base\ModuleDef> moduleDef) -> <\PhalconPlus\Base\AbstractModule>
        {
            if isset(this->activeModules[moduleDef->getName()]) {
                throw new \Exception("Module already loaded: " . moduleDef->getName());
            }
            if is_null(this->di) {
                throw new \Exception("DI doesn't load yet, failed to register module " . moduleDef->getName());
            }
            // 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 = "", moduleConf = null;
            // 全局配置
            let globalConfPath = Sys::getGlobalConfigPath();
            if !is_file(globalConfPath) {
                throw new \Phalcon\Config\Exception("Global config file not exist, file position: " . globalConfPath);
            }
            let this->config = new \Phalcon\Config(this->load(globalConfPath));

            // 初始化主模块
            let this->primaryModuleDef = new \PhalconPlus\Base\ModuleDef(this, APP_MODULE_DIR, true);
            // 定义工作模式
            define("APP_RUN_MODE", this->primaryModuleDef->getMode(), true);
            // 获取模块配置
            let moduleConf = this->primaryModuleDef->getConfig();
            // 合并配置，Module配置优先级更高
            this->config->merge(moduleConf);
            // 返回对象本身
            return this;
        }

        public function exec()
        {
            var handleMethod;
            // 初始化配置
            this->initConf();
            let handleMethod = "exec" . this->primaryModuleDef->getMapClassName();
            return call_user_func_array([this, handleMethod], func_get_args());
        }

        public function execModule(var uri = null, bool needHandle = true)
        {
            // 如果被直接调用需要自己加载配置
            if empty(this->config) {
                this->initConf();
            }
            // 应用初始化
            let this->di = new \Phalcon\DI\FactoryDefault();
            let this->application = new \Phalcon\Mvc\Application();
            this->application->setDI(this->di);

            // 加载Web模式依赖
            this->load(APP_ROOT_COMMON_LOAD_DIR . "default-web.php");
            // 把自己注入di
            this->di->setShared("bootstrap", this);
            // 注册模块
            this->registerModule(this->primaryModuleDef);

            // 如果不需要handle，则直接返回
            if !needHandle { return true; }

            // 运行
            try {
                echo this->application->handle(uri)->getContent();
            } catch \Phalcon\Mvc\Application\Exception {
                var router, newUri;
                let router = this->di->get("router");
                let newUri = "/" . router->getDefaultModule() . router->getRewriteUri();
                echo this->application->handle(newUri)->getContent();
            }
        }

        public function execSrv(bool needHandle = true)
        {
            var backendSrv = null;

            if empty(this->config) {
                this->initConf();
            }

            let this->di = new \Phalcon\DI\FactoryDefault();
            this->di->setShared("bootstrap", this);
            this->load(APP_ROOT_COMMON_LOAD_DIR . "default-web.php");

            // 注册模块
            this->registerModule(this->primaryModuleDef);

            if !needHandle { return true; }

            // Yar Server
            let backendSrv = new \PhalconPlus\Base\BackendServer(this->di);
            let this->application = new \Yar_Server(backendSrv);

            // 运行
            this->application->handle();
        }

        public function execTask(array argv, <\Phalcon\DI\FactoryDefault> di = null, var needHandle = true)
        {
            if empty(this->config) {
                this->initConf();
            }

            if is_null(di) || ! (di instanceof \Phalcon\DI\FactoryDefault\CLI) {
                let this->di = new \Phalcon\DI\FactoryDefault\CLI();
            } else {
                let this->di = di;
            }

            let this->application = new \Phalcon\CLI\Console();
            this->application->setDI(this->di);

            this->load(APP_ROOT_COMMON_LOAD_DIR . "default-cli.php");
            this->di->setShared("bootstrap", this);

            // 注册模块
            this->registerModule(this->primaryModuleDef);

            if !needHandle { return true; }

            // 运行
            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 \Exception("Module not exists: " . name);
            }
            return this->activeModules[name];
        }

        public function getModule(string! name) -> <\PhalconPlus\Base\AbstractModule>
        {
            if !isset(this->activeModules[name]) {
                throw new \Exception("Module not exists: " . name);
            }
            return this->activeModules[name];
        }

        public function getModuleDef(string! name) -> <\PhalconPlus\Base\ModuleDef>
        {
            if !isset(this->activeModules[name]) {
                throw new \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);

            // 保留被依赖的模块的配置, @deprecated
            // Use `$bootstrap->getModuleDef($moduleName)->getConfig()` instead
            this->di->set("moduleConfig", moduleDef->getConfig());

            // 参与合并的模块配置
            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 getDI() -> <\Phalcon\DI>
        {
            return this->di;
        }

        public function load(var filePath)
        {
            if !is_file(filePath) {
                throw new \Exception("The file you try to load is not exists. file position: " . filePath);
            }

            var rootPath, loader, config, application, bootstrap, di;

            let
              rootPath = "rootPath",
              loader = "loader",
              config = "config",
              application = "application",
              bootstrap = "bootstrap",
              di = "di";

            let {rootPath} = APP_ROOT_DIR;
            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
            ]);
            */
            return require filePath;
        }
    }