/** * 检查文件是否存在 * @param string $tpl 模板文件 * @throws Exception */ private function _checkFile($tpl) { $tpl = \H2O::getAlias($tpl); if (!file_exists($tpl)) { throw new \Exception($tpl . ':template is not found!'); } }
/** * 执行方法 */ public function handleRequest() { $request = \H2O::getContainer('request'); //获取HTTP请求组件 $route = $request->getRoute(); $module = \H2O::getContainer('module'); return $module->runAction($route); }
/** * 初始化sphinx服务 * @param string $tag 配置标识 默认为sphinx */ public function __construct($tag = 'sphinx') { $cnfp = \H2O::getAppConfigs('sphinx'); $this->connection = new \Foolz\SphinxQL\Connection(); if (isset($cnfp[$tag])) { $conf = $cnfp[$tag]; $this->connection->setParam(['host' => $conf['host'], 'port' => $conf['port']]); //设置连接参数 } }
/** * 初始化应用 * @param string $tag 邮箱配置标识 * config example [ 'mailer' => [ 'default' => [ 'host' => 'smtp.163.com', 'port' => 25, 'from' => ['*****@*****.**'=>'测试公司'], 'username' => '*****@*****.**', 'password' => 'password' ], 'test' => [ 'host' => 'smtp.163.com', 'port' => 25, 'from' => ['*****@*****.**'=>'测试公司'], 'username' => '*****@*****.**', 'password' => 'password' ] ] ] */ public function __construct($tag = 'default') { $mailconf = \H2O::getAppConfigs('mailer'); if (empty($mailconf)) { throw new \Exception('Mailer config params is error'); } else { if (isset($mailconf[$tag])) { $this->_config = $mailconf[$tag]; $this->_transport = $this->_getTransport($this->_config); } else { throw new \Exception('Mailer config params is error: ' . $tag); } } }
/** * 初始化连接数据库句柄 * @param string $dsntag 数据库配置标识 方便多库调用 默认为db */ private function __construct($dsntag = 'db') { $db = \H2O::getAppConfigs('db'); $this->dsntag = $dsntag; if (isset($db[$dsntag])) { //配置参数存在 $config = $db[$dsntag]; //获取数据配置信息 $this->_checkconfig($config); $this->_open(); } else { //如果配置参数存在,则直接抛弃异常 throw new \Exception('Connect failure config is not found"' . $this->dsntag); } }
/** * 显示命令输入帮助信息 */ public function help() { Stdout::title('This is H2O version ' . \H2O::getVersion()); //命令行引导入口信息 $index = $GLOBALS['argv'][0]; //命令行使用 Stdout::table([['route', 'COMMAND <route> [--option1=value1 --option2=value2 ... ]'], ['example for system module', $index . ' @migrate.create --name=all'], ['example for user define', $index . ' hello.index --test=info']]); //数据迁移模块 Stdout::table([['migrate', 'Manages application migrations', 'Params list'], ['@migrate.create', 'Create a new migrate', '--name=test'], ['@migrate.up', 'Update a new migrate', '--name=test'], ['@migrate.restore', 'Restore a new migrate', '--name=test'], ['@migrate.all', 'Update/Restore all migrate', '--type=up'], ['', '', '--type=restore']]); //后台离线服务程序 Stdout::table([['service', 'Background offline service', 'Params list'], ['@service.start', 'Start a service', '--c=hello.world'], ['@service.cat', 'Cat a service', '--c=hello.world'], ['', '', 'empty is all view all services'], ['@service.stop', 'Stop a service', '--c=hello.world'], ['', '', '--c=hello.world --p=proid'], ['', '', 'empty stop all services']]); //自动化开发工具 Stdout::table([['gii', 'Automation development tools'], ['@gii.web', 'Create web application'], ['@gii.cli', 'Create command line application'], ['@gii.model', 'Create model program '], ['@gii.simple', 'Create simple group application']]); echo Stdout::get(); exit; }
/** * 运行实例 */ public function run() { $configs = \H2O::getAppConfigs(); if (isset($configs['boot']) && !empty($configs['boot']) && is_array($configs['boot'])) { //加载引导程序 $this->_boot($configs['boot']); } $res = $this->handleRequest(); $debug = $configs['debug']; if ($debug === true) { //debug $logger = \H2O::getContainer('logger'); $logger->debugger($this->runExpend()); //记录运行状态 } echo $res; }
/** * 短信发送 * @param array $tag 配置信息模板标识 ['default','test'] 配置信息 [ 'alisms' => [ 'default' => [ 'appkey' => '23268950', //密钥 'secretKey' => '09003ad8710387cfd0742c9b7fd6aab2', //密钥 'tags' => [ 'test'=>'750_737' //短信模板标识 ] ] ] ] * @param string $m 多手机号 以逗号分隔 * @param array $data 替换变量 */ function AliSmsSend($tag, $m, $data) { $c = new \TopClient(); $smsconf = \H2O::getAppConfigs('alisms'); if (empty($smsconf)) { throw new \Exception('Ali SMS config params is error'); } else { if (isset($smsconf[$tag[0]])) { $config = $smsconf[$tag[0]]; } else { throw new \Exception('Ali SMS config params is error: ' . $tag[0]); } } $c->appkey = $config['appkey']; $c->secretKey = $config['secretKey']; $req = new \OpenSmsSendmsgRequest(); $smrequest = new \SendMessageRequest(); $em = explode(',', $m); $ids = explode('_', $config['tags'][$tag[1]]); $smrequest->template_id = $ids[0]; //模板ID $smrequest->signature_id = $ids[1]; //签名ID $smrequest->context = json_decode(json_encode($data)); //模板变量替换 foreach ($em as $v) { // $smrequest->external_id="demo"; // $smrequest->mobile="18610638306,13520839197"; $smrequest->mobile = $v; // $smrequest->device_limit="123"; // $smrequest->session_limit="123"; // $smrequest->device_limit_in_time="123"; // $smrequest->mobile_limit="123"; // $smrequest->session_limit_in_time="123"; // $smrequest->mobile_limit_in_time="123"; // $smrequest->session_id="demo"; // $smrequest->domain="demo"; // $smrequest->device_id="demo"; $req->setSendMessageRequest(json_encode($smrequest)); $resp = $c->execute($req); return $resp->result->successful; } }
/** * 根据队列配置启动队列 只支持单个子进程任务 */ private function _startProc() { $adaemons = \H2O::getAppConfigs('daemon'); $tasks = $this->_getTasksName(); foreach ($adaemons['route'] as $route) { $tmpdir = $this->_logpath . 'daemon' . DS . strtolower($route); //当前任务日志目录 file::createDirectory($tmpdir); //如果目录不存在,则创建 $_logFile = $tmpdir . DS . date('Ymd') . '.log'; //根据路由规则按天记录 if (!in_array($route, $tasks)) { //每个任务只充许一个进程在执行 $_cmd = "{$this->_daemonson} @service.daemon --c={$route} >>{$_logFile} 2>&1 &" . PHP_EOL; $_pp = popen($_cmd, 'r'); pclose($_pp); } } }
/** * 执行方法 */ public function handleRequest() { $request = \H2O::getContainer('request'); //控制台请求 $route = $request->getRoute(); if (strncmp($route['controller'], '@', 1) === 0) { //当有前缀@时为,则为系统控制台模块 $sclass = '\\H2O\\console\\' . ucfirst(substr($route['controller'], 1)); $o = \H2O::createObject($sclass); $action = 'act' . ucfirst($route['action']); if (method_exists($o, $action)) { call_user_func([$o, $action]); } else { throw new \Exception($sclass . ' no method:' . $action); } } else { $module = \H2O::getContainer('module'); return $module->runAction($route); } }
/** * 构造函数 */ public function __construct() { $this->_apppath = \H2O::getAppRootPath(); }
/** * 执行动作 * @param array $route 路由 */ public function runAction($route) { $o = \H2O::createObject($this->_ctrnSpace . '\\' . $route['controller']); return $o->runAction(ucfirst($route['action'])); }
/** * 启动 */ public function actStart() { $routep = $this->_getRoutePath(); //路由规则path $logfile = $this->_logpath . $routep . DS . date('Ymd') . '.log'; //记录日志信息 按天记录 $module = \H2O::getContainer('module'); $route = \H2O\base\Module::parseRoute($routep); //返回路由规则URL //启动时,要删除已产生的停止信号,防止启动时就退出 $this->_deleteSignal($routep); //写入进程信息 $pid = getmypid(); $pidfile = $this->_logpath . $routep . '.pid'; //进程存储文件 File::write($pidfile, $pid . ':' . date('Y-m-d H:i:s') . PHP_EOL); //写入存储信息 //循环业务处理 while (true) { $signal = $this->_getSignal($routep); //获取信号 if ($signal[0] == $this->_stopsignal) { //信号源为停止,并且是当前应用 //清理进程信息 if ($signal[1] == $pid) { $apid = file($pidfile); //读取所有进程信息 $apid = array_filter($apid); //过滤空格 $tmpid = []; foreach ($apid as $ap) { $ap = trim($ap); $opid = substr($ap, 0, strpos($ap, ':')); if ($opid != $pid && !empty($ap)) { $tmpid[] = $ap . PHP_EOL; } } if (empty($tmpid)) { //如果不存进程信息时,直接删除记录进程日志信息 File::remove($pidfile); //删除运行时的日志 } else { File::write($pidfile, implode('', $tmpid), false); //新写入进程日志 } } else { File::remove($pidfile); //删除运行时的日志 } exit; } else { $octr = $module->getController($route['controller']); //控制器对象 $gwmethod = 'Gate' . ucfirst($route['action']); //方法网关 if (method_exists($octr, $gwmethod)) { //增加入口应用关口,可在此函数中处理业务逻辑,可实现定时任务等 if ($octr->{$gwmethod}()) { //返回值只有为true时才执行相应的程序 $res = $octr->runAction(ucfirst($route['action'])); //执行操作 $content = 'pid:' . $pid . ' datetime:' . date('Y-m-d H:i:s') . ' response:' . $res . PHP_EOL; File::write($logfile, $content); //写入日志信息 } } else { $res = $octr->runAction(ucfirst($route['action'])); //执行操作 $content = 'pid:' . $pid . ' datetime:' . date('Y-m-d H:i:s') . ' response:' . $res . PHP_EOL; File::write($logfile, $content); //写入日志信息 } } sleep(1); //休眠时间 1秒 } }
/** * 应用初始化时的配置信息缓存 * @param array $configs 应用配置信息 */ public static function setAppConfigs($configs) { self::$_appconfigs = $configs; }
function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) { $dirParts = explode(DS, $___viewFn); array_pop($dirParts); $templatePath = implode(DS, $dirParts); $options = array('template_path' => $templatePath, 'compile_path' => H2O_COMPILE_PATH, 'auto_render' => $this->h2oAutoRender, 'cache' => $this->h2oEnableCache, 'safeClass' => array('SimplePie_Item')); $h2o = new H2O($___viewFn, $options); $viewVars =& $___dataForView; $passVarsH2o = explode(',', 'here,base,action,name,pageTitle,layoutPath,webroot'); foreach ($this->__passedVars as $var) { if (in_array($var, $passVarsH2o)) { $viewVars[Inflector::underscore($var)] = $this->{$var}; } } $viewVars['data'] = $this->data; if ($this->helpers != false && $loadHelpers === true) { $loadedHelpers = array(); $loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers); foreach (array_keys($loadedHelpers) as $helper) { $replace = strtolower(substr($helper, 0, 1)); $camelBackedHelper = preg_replace('/\\w/', $replace, $helper, 1); ${$camelBackedHelper} =& $loadedHelpers[$helper]; if (is_array(${$camelBackedHelper}->helpers) && !empty(${$camelBackedHelper}->helpers)) { $subHelpers = ${$camelBackedHelper}->helpers; foreach ($subHelpers as $subHelper) { ${$camelBackedHelper}->{$subHelper} =& $loadedHelpers[$subHelper]; } } $helper = $this->loaded[$camelBackedHelper] =& ${$camelBackedHelper}; $h2o->set($camelBackedHelper, $helper); //$h2o->storage['helpers'][$camelBackedHelper] = $helper; } } if ($this->helpers != false && $loadHelpers === true) { foreach ($loadedHelpers as $helper) { if (is_object($helper)) { if (is_subclass_of($helper, 'Helper') || is_subclass_of($helper, 'helper')) { $helper->beforeRender(); } } } } if (isset($myPaginate)) { $paginator = $myPaginate; } $paginator->h2o_safe = array('prev', 'numbers', 'next'); $viewVars['paginate'] = $paginator; $h2o->evaluate($viewVars); $___viewFn = $h2o->compiled_file; extract($___dataForView, EXTR_SKIP); $BASE = $this->base; $params =& $this->params; $page_title = $this->pageTitle; ob_start(); if (Configure::read() > 0) { include $___viewFn; } else { @(include $___viewFn); } if ($this->helpers != false && $loadHelpers === true) { foreach ($loadedHelpers as $helper) { if (is_object($helper)) { if (is_subclass_of($helper, 'Helper') || is_subclass_of($helper, 'helper')) { $helper->afterRender(); } } } } $out = ob_get_clean(); if (isset($this->loaded['cache']) && $this->cacheAction != false && (defined('CACHE_CHECK') && CACHE_CHECK === true)) { if (is_a($this->loaded['cache'], 'CacheHelper')) { $cache =& $this->loaded['cache']; if ($cached === true) { $cache->view =& $this; } $cache->base = $this->base; $cache->here = $this->here; $cache->helpers = $this->helpers; $cache->action = $this->action; $cache->controllerName = $this->name; $cache->layout = $this->layout; $cache->cacheAction = $this->cacheAction; $cache->cache($___viewFn, $out, $cached); } } //$this->output = $out; return $out; }
/** * @param $curoute 当前路由名称 */ private function getRealPath($curoute) { if (empty($this->_routeTable)) { return $curoute; } else { if (is_string($this->_routeTable)) { //通过API模块查寻真实URL if (strpos($this->_routeTable, '.') === false) { //如果填写不存在方法名直接报错 throw new \Exception('Configs of `request` params is error!'); } else { //自定义路由 $ao = explode('.', $this->_routeTable); $o = \H2O::createObject($ao[0]); $rroute = call_user_func([$o, 'act' . ucfirst($ao[1])]); return empty($rroute) ? $curoute : $rroute; } } else { $ecur = explode('/', $curoute); $lecur = count($ecur); if (isset($this->_routeTable[$ecur[0]])) { $rpath = $this->_routeTable[$ecur[0]]; if (is_array($rpath)) { for ($i = 1; $i < $lecur; $i++) { if (isset($rpath[$i])) { self::$getParams[$rpath[$i]] = $ecur[$i]; } } return $rpath[0]; } else { return $rpath; } } else { return $curoute; } } } }
/** * 翻页数据 * @param int $size 每页显示条数 * @param string $param 翻页参数名 * @return array */ public function pageData($size = 20, $param = 'page') { $request = \H2O::getContainer('request'); //获取当前页 $cpage = $request->get($param); $cpage = empty($cpage) ? 1 : intval($cpage); $cpage = $cpage < 1 ? 1 : $cpage; $sql = $this->getRawSql(); //获取解析后的SQL $total = $this->rowCount($sql); //总记录数 $data = $this->setSql($sql . ' LIMIT ' . ($cpage - 1) * $size . ',' . $size)->fetchAll(); //获取当前页数据 //总页数 $ptotal = empty($total) ? 1 : ceil($total / $size); //下一页 $next = $cpage + 1; if ($next > $ptotal) { $next = $ptotal; } //上一页 $up = $cpage - 1; if ($up < 1) { $up = 1; } $page = ['param' => $param, 'size' => $size, 'page' => $cpage, 'last' => $ptotal, 'next' => $next, 'prev' => $up, 'total' => $total]; return ['page' => $page, 'data' => $data]; }
/** * 守护子进程 */ public function actDaemon() { $routep = $this->_getRoutePath(); //路由规则path $module = \H2O::getContainer('module'); $route = \H2O\base\Module::parseRoute($routep); //返回路由规则URL $octr = $module->getController($route['controller']); //控制器对象 $gwmethod = 'Gate' . ucfirst($route['action']); //方法网关 $pid = getmypid(); //进程ID if (method_exists($octr, $gwmethod)) { //增加入口应用关口,可在此函数中处理业务逻辑,可实现定时任务等 $gwm = $octr->{$gwmethod}(); if ($gwm === true) { //返回值只有为true时才执行相应的程序 $res = $octr->runAction(ucfirst($route['action'])); //执行操作 $response = 'pid:' . $pid . ' datetime:' . date('Y-m-d H:i:s') . ' response:' . $res . PHP_EOL; } } else { $res = $octr->runAction(ucfirst($route['action'])); //执行操作 $response = 'pid:' . $pid . ' datetime:' . date('Y-m-d H:i:s') . ' response:' . $res . PHP_EOL; } echo $response; }
/** * 异常日志 * @param Exception $exception 异常信息 */ public function logException($exception) { $data = $this->parseException($exception); $logger = \H2O::getContainer('logger'); $env = \H2O::getRunEnv(); //获取运行环境 if ($env == 'prod') { //生产环境 $logger->exceptionWrite($data['message'], $data['files']); //写入错误日志 } else { //开发、测试环境 都直接显示错误 $logger->exceptionDebug($data['message'], $data['files']); //显示错误日志 方便调试 } if ($this->discardExistingOutput) { $this->clearOutput(); } }
/** * 返回模板渲染后的字符串 * @param string $tpl 模板文件 * @param array $vars 需要传入模板的数据参数 */ public function render($tpl, $vars = []) { $ov = \H2O::getContainer('view'); $ov->setFile($tpl); $ov->setController(new static()); //设置依附的控制器 $ov->setPath($this->getViewPath()); $ov->setContent($this->getContent()); $vars = array_merge(self::$viewglobalvars, $vars); //合并全局变量和局部变量 $content = $ov->render($vars); if (empty($this->_layout) || !empty($this->_content)) { //非布局 或者已有内容信息,则当前已为布局模块 return $content; } else { //有布局 $route = Module::parseRoute($this->_layout); $o = \H2O::createObject($this->_namespace . '\\' . $route['controller']); $o->setContent($content); //设置主模块缓存 return call_user_func([$o, 'act' . ucfirst($route['action'])]); } }
/** * 更新/恢复该版本下所有迁移模块 */ public function actAll() { $request = \H2O::getContainer('request'); //控制台请求 $params = $request->getParams(); if (empty($params['type'])) { echo 'Missing required parameter: type' . PHP_EOL; exit; } $mtype = 'act' . ucfirst($params['type']); //更新类型 up/restore $all = $this->_namespace . '\\All'; //全量数据列表 $oall = new $all(); if (!method_exists($oall, 'Regtable')) { echo $all . ' is not found method: regtable' . PHP_EOL; exit; } $regnames = $oall->Regtable(); //获取所有注册到全量的数据信息 if (empty($regnames) || !is_array($regnames)) { echo $all . ':regtable return value is empty or is not array!' . PHP_EOL; exit; } foreach ($regnames as $reg) { try { $class = $this->_namespace . '\\' . ucfirst($reg); $oc = new $class(); $oc->clearBuildSQL(); //清空上一个模块的SQL,防止重复写入 $oc->beginTransaction(); $oc->{$mtype}(); $oc->buildExec(); //执行SQL $oc->pdo->commit(); } catch (\Exception $e) { $oc->pdo->rollBack(); //回滚 throw new \ErrorException(PHP_EOL . 'Class name:' . $class . ',' . $e->getMessage()); } } echo 'Executed successfully!' . PHP_EOL; exit; }
/** * @return array 开发者信息 */ private function _devauthor() { $config = \H2O::getAppConfigs('devauthor'); //读取开发者配置信息 return ['T_PROGRAM' => isset($config['program']) ? $config['program'] : '', 'T_AUTHOR' => isset($config['author']) ? $config['author'] : '', 'T_DEVTIME' => date('Y-m-d H:i:s')]; }
/** * 写入debugger日志 * @param array $data 消耗信息 */ public function debugger($data) { $request = \H2O::getContainer('request'); Stdout::title('Debugger Info ' . date('Y-m-d H:i:s')); Stdout::table([['Route', 'RunTime', 'Memory'], [$request->getRequestUri(), $data['runtime'], $data['memory']]]); $logfile = APP_RUNTIME . DS . 'console' . DS . 'debugger' . DS . date('Ymd') . '.log'; //异常日志文件 $content = Stdout::get(); //内容 H2O\helpers\File::write($logfile, $content); //写入日志信息 }
/** * 返回请求信息 * @return 返回请求句柄 */ public function request() { return \H2O::getContainer('request'); }