Controller.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <?php
  2. namespace Heanup\Frame;
  3. abstract class Controller
  4. {
  5. protected $tpl; // 模板路径, 可选
  6. protected $queryObj;
  7. protected $data_name = false;
  8. protected $isrestful = false;
  9. final public function __construct()
  10. {
  11. $this->queryObj = $this->getQuery();
  12. }
  13. /**
  14. * 主逻辑
  15. */
  16. final public function run()
  17. {
  18. try {
  19. $this->before();
  20. $method = strtolower($_SERVER['REQUEST_METHOD']);
  21. if ($method == 'options') {
  22. $this->optionsData();
  23. }
  24. $this->checkAuth();
  25. $data_name = $method . 'Data';
  26. if ($this->isrestful) {
  27. if (!method_exists(get_called_class(), $data_name)) {
  28. Response::sendResponse(405, ['method' => strtoupper($method)], 'Method not allowed');
  29. die();
  30. }
  31. $this->$data_name();
  32. } else {
  33. $this->main();
  34. }
  35. } catch (\Exception $ex) {
  36. $this->showError($ex->getCode(), $ex->getMessage());
  37. }
  38. }
  39. public function optionsData()
  40. {
  41. header("HTTP/1.1 200");
  42. header("Access-Control-Allow-Origin: *");
  43. header("Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE");
  44. // header("Access-Control-Max-Age: 3");
  45. header("Access-Control-Allow-Headers: lang,token,content-type");
  46. die();
  47. }
  48. /**
  49. * 尽快输出结果,然后执行后续逻辑
  50. * 本方法的的信息不会被输出
  51. * 即使exit之后仍旧能被执行
  52. */
  53. final public function __destruct()
  54. {
  55. if (function_exists('fastcgi_finish_request')) {
  56. fastcgi_finish_request();
  57. }
  58. $this->after();
  59. }
  60. /**
  61. * 前置方法,处理参数
  62. */
  63. protected function before()
  64. {
  65. }
  66. /**
  67. * 执行验证
  68. */
  69. protected function checkAuth()
  70. {
  71. }
  72. /**
  73. * 执行逻辑
  74. */
  75. protected function main()
  76. {
  77. }
  78. /**
  79. * 后续方法
  80. */
  81. protected function after()
  82. {
  83. }
  84. /**
  85. * @return Filter
  86. */
  87. protected function getRequest()
  88. {
  89. static $instance = null;
  90. parse_str(file_get_contents('php://input'), $data);
  91. $data = array_merge($_POST, $_GET, $_COOKIE, $data);
  92. if (is_null($instance)) {
  93. $instance = new Filter($data);
  94. }
  95. return $instance;
  96. }
  97. /**
  98. * @return Filter
  99. */
  100. protected function getPut()
  101. {
  102. static $instance = null;
  103. try {
  104. $putData = file_get_contents("php://input");
  105. $resultData = json_decode($putData, true);
  106. if (is_array($resultData)) {
  107. //解析IOS提交的PUT数据
  108. $data = $resultData;
  109. } elseif (!strstr($putData, "\r\n")) {
  110. //解析本地测试工具提交的PUT数据
  111. parse_str($putData, $putData);
  112. $data = $putData;
  113. } else {
  114. //解析PHP CURL提交的PUT数据
  115. $putData = explode("\r\n", $putData);
  116. $resultData = [];
  117. foreach ($putData as $key => $data) {
  118. if (substr($data, 0, 20) == 'Content-Disposition:') {
  119. $match = explode(";", $data);
  120. if (count($match) == 2) {
  121. preg_match('/.*\"(.*)\"/', $data, $matchName);
  122. $resultData[$matchName[1]] = $putData[$key + 2];
  123. } else {
  124. $info = self::parserInfo($data);
  125. $file = fopen($info['tmp_name'], "r+");
  126. fwrite($file, $putData[$key + 3]);
  127. fclose($file);
  128. $resultData[$info['field']] = $info;
  129. }
  130. }
  131. }
  132. $data = $resultData;
  133. }
  134. } catch (\Exception $e) {
  135. $data = [];
  136. }
  137. if (is_null($instance)) {
  138. $instance = new Filter($data);
  139. }
  140. return $instance;
  141. }
  142. private static function parserInfo($data, $options = ['saveFile' => true])
  143. {
  144. //获取参数名称, type
  145. $infoPattern = '/name="(.+?)"(; )?(filename="(.+?)")?/'; //todo: 待优化
  146. preg_match($infoPattern, $data, $matches);
  147. $info['field'] = $matches[1];
  148. $info['type'] = 'json';
  149. //如果是文件
  150. if (count($matches) > 4) {
  151. $info['type'] = 'file';
  152. $info['name'] = $matches[4];
  153. //如果设置保存文件, 保存到临时文件
  154. if (isset($options['saveFile']) && $options['saveFile']) {
  155. $tmpFile = tempnam(sys_get_temp_dir(), 'FD');
  156. $info['tmp_name'] = $tmpFile;
  157. }
  158. }
  159. return $info;
  160. }
  161. protected function getJson()
  162. {
  163. static $instance = null;
  164. $data = file_get_contents('php://input');
  165. $data = json_decode($data, true) ?: [];
  166. if (is_null($instance)) {
  167. $instance = new Filter($data);
  168. }
  169. return $instance;
  170. }
  171. /**
  172. * @return Filter
  173. */
  174. protected function getQuery()
  175. {
  176. static $instance = null;
  177. if (is_null($instance)) {
  178. $instance = new Filter($_GET);
  179. }
  180. return $instance;
  181. }
  182. protected function getFilter()
  183. {
  184. $str = $this->getQuery()->string("filter");
  185. $str = explode(";", $str);
  186. if ($str) {
  187. foreach ($str as $item) {
  188. $item = explode(":", $item);
  189. if ($item[1] == "") {
  190. continue;
  191. }
  192. $_Filter[$item[0]] = $item[1];
  193. }
  194. }
  195. $_Filter['page'] = $_GET['page'] ?: ($_Filter['page'] ?: 1);
  196. $_Filter['pageSize'] = $_GET['pageSize'] ?: ($_Filter['pageSize'] ?: 20);
  197. static $instance = null;
  198. if (is_null($instance)) {
  199. $instance = new Filter($_Filter);
  200. }
  201. return $instance;
  202. }
  203. /**
  204. * @return Filter
  205. */
  206. protected function getPost()
  207. {
  208. static $instance = null;
  209. if (is_null($instance)) {
  210. $instance = new Filter($_POST);
  211. }
  212. return $instance;
  213. }
  214. /**
  215. * 获取模板, 固定模板, 与controller名称类似
  216. * @return Template
  217. */
  218. protected function getTemplate()
  219. {
  220. static $template;
  221. if ($template) {
  222. return $template;
  223. }
  224. $class = get_called_class();
  225. $class = explode('\\', $class);
  226. $path = dirname(__DIR__) . '/' . implode('/', array_slice($class, 1, 2)) . '/Template/';
  227. if (!$this->tpl) {
  228. $this->tpl = implode('/', array_slice($class, 4));
  229. }
  230. $template = new Template();
  231. $template->setPath($path)->setTpl($this->tpl);
  232. $data = get_object_vars($this);
  233. if ($data) {
  234. $template->assign($data);
  235. }
  236. return $template;
  237. }
  238. /**
  239. * 检查CSRF攻击
  240. * @return bool
  241. */
  242. protected function checkCsrf()
  243. {
  244. $host = strtolower(trim($_SERVER['HTTP_HOST']));
  245. $referer = parse_url($_SERVER['HTTP_REFERER']);
  246. $referer = substr(strtolower(trim($referer['host'])), -(strlen($host)));
  247. if (!empty($referer) AND $referer != $host AND $referer != ('www.' . $host)) {
  248. return false;
  249. }
  250. return true;
  251. }
  252. }