Application.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. <?php
  2. namespace Qii;
  3. use \Qii\Base\Dispatcher;
  4. use \Qii\Autoloader\Factory;
  5. use \Qii\Autoloader\Import;
  6. use \Qii\Autoloader\Psr4;
  7. use \Qii\Autoloader\Instance;
  8. use \Qii\Config\Register;
  9. use \Qii\Config\Consts;
  10. use \Qii\Config\Setting;
  11. class Application
  12. {
  13. /**
  14. * 存储网站配置文件内容
  15. *
  16. * @var array $config 配置内容
  17. */
  18. protected static $config = [];
  19. /**
  20. * @var object $logerWriter 写日志工具
  21. */
  22. public $logerWriter = null;
  23. /**
  24. * @var string $workspace 工作目录
  25. */
  26. private static $workspace = './';/**
  27. * @var string $env 环境变量
  28. */
  29. public static $env = 'product';
  30. /**
  31. * @var array $paths 网站使用的路径
  32. */
  33. public static $paths = array('configure', 'controller', 'model', 'view', 'plugins', 'tmp');
  34. /**
  35. * Qii\Request\Url
  36. */
  37. public $request;
  38. /**
  39. * 分发器
  40. */
  41. public $dispatcher = null;
  42. public function __construct()
  43. {
  44. $this->helper = Psr4::getInstance()->loadClass('\Qii\Autoloader\Helper');
  45. }
  46. /**
  47. * 初始化本实例对象
  48. *
  49. * @return object
  50. */
  51. public static function getInstance()
  52. {
  53. $args = func_get_args();
  54. if (count($args) > 0) {
  55. $className = array_shift($args);
  56. return Psr4::getInstance($className);
  57. }
  58. return Factory::getInstance('\Qii\Application');
  59. }
  60. /**
  61. * 设置网站运行环境
  62. *
  63. * @param string $env 网站环境
  64. * @return $this
  65. */
  66. public function setEnv($env)
  67. {
  68. self::$env = $env;
  69. return $this;
  70. }
  71. /**
  72. * 设置缓存文件路径
  73. * @param string $path 缓存路径
  74. */
  75. public function setCachePath($path)
  76. {
  77. Register::set(Consts::APP_CACHE_PATH, $this->getCachePath($path));
  78. return $this;
  79. }
  80. /**
  81. * 保存网站的配置文件
  82. *
  83. * @param $iniFile
  84. */
  85. public function setAppIniFile($iniFile)
  86. {
  87. Register::set(Consts::APP_INI_FILE, $iniFile);
  88. return $this;
  89. }
  90. /**
  91. * 设置网站的工作目录,可以通过此方法将网站的重要文件指向到其他目录
  92. *
  93. * @param string $workspace 工作目录
  94. * @return $this
  95. */
  96. public function setWorkspace($workspace = './')
  97. {
  98. //此处转换成真实路径,防止workspace中引入的文件出错
  99. if (!is_dir($workspace)) {
  100. throw new \Qii\Exceptions\FolderDoesNotExist(\Qii::i(1045, $workspace), __LINE__);
  101. }
  102. $workspace = Psr4::getInstance()->realpath($workspace);
  103. Psr4::getInstance()->removeNamespace('workspace', self::$workspace);
  104. //如果配置了使用namespace就走namespace
  105. self::$workspace = $workspace;
  106. Psr4::getInstance()->addNamespace('workspace', $workspace, true);
  107. foreach (self::$paths AS $path) {
  108. Psr4::getInstance()->addNamespace($path, $workspace . '\\' . $path);
  109. }
  110. return $this;
  111. }
  112. /**
  113. * 获取指定路径的缓存绝对路径
  114. * @param string $path 路径
  115. * @return string 绝对路径
  116. */
  117. public function getCachePath($path)
  118. {
  119. if (self::$workspace != '') return self::$workspace . DS . $path;
  120. $dir = '';
  121. $workspace = sr4::getInstance()->getNamespace('workspace');
  122. foreach ($workspace AS $dir) {
  123. if (is_dir($dir)) $dir = $dir;
  124. }
  125. return $dir . DS . $path;
  126. }
  127. /**
  128. * 获取网站运行环境
  129. *
  130. * @return string
  131. */
  132. public function getEnv()
  133. {
  134. return self::$env;
  135. }
  136. /**
  137. * 获取当前工作目录
  138. */
  139. public function getWorkspace()
  140. {
  141. return self::$workspace;
  142. }
  143. /**
  144. * 获取网站的配置文件
  145. * @return Config\Mix
  146. */
  147. public function getAppIniFile()
  148. {
  149. return Register::get(Consts::APP_INI_FILE);
  150. }
  151. /**
  152. * 设置网站配置文件
  153. * @param string $ini 配置文件路径
  154. * @param string $env 环境
  155. *
  156. */
  157. public function setAppConfigure($ini, $env = '')
  158. {
  159. if ($env == '') $env = $this->getEnv();
  160. $ini = Psr4::getInstance()->getFileByPrefix($ini);
  161. $this->setAppIniFile($ini);
  162. if (!Register::setAppConfigure(
  163. $ini,
  164. $env
  165. )
  166. ) throw new \Qii\Exceptions\FileNotFound($ini, 404);
  167. //载入request方法
  168. $this->request = Psr4::getInstance()->loadClass('\Qii\Request\Http');
  169. Setting::getInstance()->setDefaultTimeZone();
  170. Setting::getInstance()->setDefaultControllerAction();
  171. Setting::getInstance()->setDefaultNamespace();
  172. Setting::getInstance()->setDefaultLanguage();
  173. return $this;
  174. }
  175. /**
  176. * 合并ini文件生成的数组
  177. * @param String $iniFile ini文件名
  178. * @param Array $array
  179. */
  180. public function mergeAppConfigure($iniFile, $array)
  181. {
  182. if (!is_array($array)) return;
  183. Register::mergeAppConfigure($iniFile, $array);
  184. return $this;
  185. }
  186. /**
  187. * 覆盖/添加ini文件的key对应的值
  188. * @param String $iniFile ini文件名
  189. * @param String $key
  190. * @param String $val
  191. */
  192. public function rewriteAppConfigure($iniFile, $key, $val)
  193. {
  194. Register::rewriteConfig($iniFile, $key, $val);
  195. return $this;
  196. }
  197. /**
  198. * 设置指定的前缀是否使用命名空间
  199. * @param string $prefix 前缀
  200. * @param bool $useNamespace 是否使用
  201. * @return $this
  202. */
  203. public function setUseNamespace($prefix, $useNamespace = true)
  204. {
  205. Psr4::getInstance()->setUseNamespace($prefix, $useNamespace);
  206. return $this;
  207. }
  208. /**
  209. * 添加命名空间对应的网站目录
  210. * @param string $prefix 前缀
  211. * @param string $baseDir 对应的路径
  212. * @param bool $prepend 是否追加
  213. * @return $this
  214. */
  215. public function addNamespace($prefix, $baseDir, $prepend = false)
  216. {
  217. if (!is_dir($baseDir)) {
  218. throw new \Qii\Exceptions\FolderDoesNotExist(\Qii::i(1009, $baseDir), __LINE__);
  219. }
  220. $baseDir = Psr4::getInstance()->realpath($baseDir);
  221. Psr4::getInstance()->addNamespace($prefix, $baseDir, $prepend);
  222. return $this;
  223. }
  224. /**
  225. * 设置启动前执行的方法
  226. *
  227. * @return $this
  228. * @throws Exception
  229. */
  230. public function setBootstrap()
  231. {
  232. Psr4::getInstance()->loadFileByClass('Bootstrap');
  233. if (!class_exists('Bootstrap', false)) throw new \Qii\Exceptions\ClassNotFound(\Qii::i(1405, 'Bootstrap'), __LINE__);;
  234. $bootstrap = Psr4::getInstance()->instance('Bootstrap');
  235. if (!$bootstrap instanceof \Qii\Base\Bootstrap) {
  236. throw new \Qii\Exceptions\ClassInstanceof(Qii::i(1107, 'Bootstrap', 'Qii\Bootstrap'), __LINE__);;
  237. }
  238. $refectionClass = new \ReflectionClass('Bootstrap');
  239. $methods = $refectionClass->getMethods();
  240. //自动执行以init开头的公共方法
  241. foreach ($methods as $method) {
  242. $name = $method->getName();
  243. if (substr($name, 0, 4) == 'init' && $method->isPublic()) $bootstrap->$name();
  244. }
  245. return $this;
  246. }
  247. /**
  248. * 设置写loger的类
  249. *
  250. * @param LogerWriter $logerCls 日志记录类
  251. */
  252. public function setLoger($logerCls)
  253. {
  254. $this->logerWriter = Instance::instance(
  255. '\Qii\Loger\Instance',
  256. Instance::instance($logerCls)
  257. );
  258. return $this;
  259. }
  260. /**
  261. * 设置缓存
  262. *
  263. * @param string $engine 缓存方法
  264. * @param array $policy 缓存策略
  265. */
  266. public function setCache($engine = '', $policy = array())
  267. {
  268. $engine = $engine == '' ? \Qii::appConfigure('cache') : $engine;
  269. $basicPolicy = array(
  270. 'servers' => $this->getCachePolicy($engine),
  271. );
  272. if ($basicPolicy['servers']) {
  273. $policy = array_merge($basicPolicy, $policy);
  274. }
  275. $loader = new \Qii\Cache\Loader($engine);
  276. return $loader->initialization($policy);
  277. }
  278. /**
  279. * 获取缓存的策略
  280. * @param String $cache 缓存的内容
  281. * @return multitype:multitype:Ambigous <>
  282. */
  283. public function getCachePolicy($cache) {
  284. $data = array();
  285. if (!$cache) return $data;
  286. $cacheInfo = Register::getAppConfigure(Register::get(Consts::APP_INI_FILE), $cache);
  287. if (!$cacheInfo) return $data;
  288. $servers = explode(";", $cacheInfo['servers']);
  289. $ports = explode(";", $cacheInfo['ports']);
  290. for ($i = 0; $i < count($servers); $i++) {
  291. $data[] = array('host' => $servers[$i], 'port' => $ports[$i]);
  292. }
  293. return $data;
  294. }
  295. /**
  296. * 设置view
  297. *
  298. * @param string $engine
  299. * @param array $policy
  300. * @return mixed
  301. */
  302. public function setView($engine = 'smarty', $policy = array()) {
  303. $viewConfigure = \Qii::appConfigure('view');
  304. //如果之前实例化过相同的就不再实例化
  305. if (!$engine) $engine = $viewConfigure['engine'];
  306. $policy = (array)$policy;
  307. if (!$policy) {
  308. $policy = array_merge($policy, $viewConfigure[$engine]);
  309. }
  310. $viewEngine = Psr4::getInstance()->loadClass('\Qii\View\Loader');
  311. $viewEngine->setView($engine, $policy);
  312. return $viewEngine;
  313. }
  314. /**
  315. * 设置数据库使用的文件
  316. *
  317. * @param $iniFile
  318. * @throws \Qii_Exceptions_Overwrite
  319. */
  320. public function setDBIniFile($iniFile)
  321. {
  322. Register::set(Consts::APP_DB, $iniFile);
  323. }
  324. /**
  325. * 获取当前数据库文件
  326. *
  327. * @return \Qii_Mix
  328. * @throws \Qii_Exceptions_Variable
  329. */
  330. public function getDBIniFile()
  331. {
  332. return Register::get(Consts::APP_DB);
  333. }
  334. /**
  335. * 设置数据库配置文件
  336. * @param string $ini 配置文件路径
  337. * @param string $env 环境
  338. */
  339. public function setDB($ini, $env = '')
  340. {
  341. if ($env == '') $env = $this->getEnv();
  342. $this->setDBIniFile($ini);
  343. if (!Register::setAppConfigure(
  344. Psr4::getInstance()->getFileByPrefix($ini),
  345. $env)
  346. ) {
  347. throw new \Qii\Exceptions\FileNotFound($ini, 404);
  348. }
  349. return $this;
  350. }
  351. /**
  352. * 设置路由规则
  353. *
  354. * @param string $router 路由配置文件位置
  355. * @return $this
  356. */
  357. public function setRouter($router)
  358. {
  359. Register::set(
  360. Consts::APP_SITE_ROUTER,
  361. Import::includes(
  362. Psr4::realpath(Psr4::getInstance()->getFileByPrefix($router)
  363. )
  364. )
  365. );
  366. //载入rewrite规则后重写request
  367. $rewrite = Psr4::loadStatic(
  368. '\Qii\Router\Parse',
  369. 'get',
  370. \Qii\Request\Url::getPathInfo(),
  371. $this->request->controller,
  372. $this->request->action,
  373. $this->request->url->get(2)
  374. );
  375. $rewrite['controller'] = $rewrite['controller'] ? $rewrite['controller'] : $this->request->defaultController();
  376. $rewrite['action'] = $rewrite['action'] ? $rewrite['action'] : $this->request->defaultAction();
  377. //是否已经rewrite,如果和url中的不一样就是已经rewrite
  378. if ($this->request->controller != $rewrite['controller'] || $this->request->action != $rewrite['action']) {
  379. $this->request->setRouted(true);
  380. }
  381. $this->request->setControllerName($rewrite['controller']);
  382. $this->request->setActionName($rewrite['action']);
  383. return $this;
  384. }
  385. /**
  386. * sprintf 格式化语言错误信息内容
  387. *
  388. * Qii::e($message, $argv1, $argv2, ..., $line);
  389. * $message = sprintf($message, $argv1, $argv2, ...);
  390. * throw new \Qii\Exceptions\Error($message, $line);
  391. */
  392. public function showError()
  393. {
  394. return call_user_func_array(array('\Qii\Exceptions\Errors', 'e'), func_get_args());
  395. }
  396. /**
  397. * 执行
  398. * @return $this
  399. * @throws \Exception
  400. */
  401. public function run()
  402. {
  403. $this->helper->load(self::$workspace);
  404. $this->dispatcher = Psr4::getInstance()->loadClass('\Qii\Base\Dispatcher');
  405. if (!$this->dispatcher instanceof \Qii\Base\Dispatcher) {
  406. throw new \Exception('Dispatcher must instance of Qii\Base\Dispatcher', __LINE__);
  407. }
  408. //如果设置了host的话,看host对应的controller路径
  409. $hosts = $this->appConfigure('hosts');
  410. if (count($hosts) > 0) {
  411. foreach ($hosts AS $host) {
  412. if ($host['domain'] == $this->request->host) {
  413. Register::set(
  414. Consts::APP_DEFAULT_CONTROLLER_PREFIX,
  415. ($host['path'] ? $host['path'] : $host['domain'])
  416. );
  417. break;
  418. }
  419. }
  420. }
  421. $this->request->setDispatcher($this->dispatcher);
  422. //rewrite规则
  423. $this->dispatcher->setRequest($this->request);
  424. $this->dispatcher->dispatch();
  425. $this->request->setDispatched(true);
  426. return $this;
  427. }
  428. }