Application.php 14 KB

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