Application.php 11 KB

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